Как работает get_comment_permalink в структуре комментариев Django? - PullRequest
3 голосов
/ 27 марта 2012

Я не совсем понимаю get_comment_permalink в структуре комментариев Джанго.

Я создал несколько комментариев для своего класса Order, используя комментарии Джанго, по умолчанию он отображает URL-адрес типа /comments/cr/18/1/#c1, и этот URL никогда не существует.

Я посмотрел на комментарий urls.py и в нем есть строка с надписью

urlpatterns += patterns('',
    url(r'^cr/(\d+)/(.+)/$', 'django.contrib.contenttypes.views.shortcut', name='comments-url-redirect'),
)

views.py, который имеет метод shortcut, равен

from django import http
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site, get_current_site
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext as _

def shortcut(request, content_type_id, object_id):
    """
    Redirect to an object's page based on a content-type ID and an object ID.
    """
    # Look up the object, making sure it's got a get_absolute_url() function.
    try:
        content_type = ContentType.objects.get(pk=content_type_id)
        if not content_type.model_class():
            raise http.Http404(_(u"Content type %(ct_id)s object has no associated model") %
                               {'ct_id': content_type_id})
        obj = content_type.get_object_for_this_type(pk=object_id)
    except (ObjectDoesNotExist, ValueError):
        raise http.Http404(_(u"Content type %(ct_id)s object %(obj_id)s doesn't exist") %
                           {'ct_id': content_type_id, 'obj_id': object_id})

    try:
        get_absolute_url = obj.get_absolute_url
    except AttributeError:
        raise http.Http404(_("%(ct_name)s objects don't have a get_absolute_url() method") %
                           {'ct_name': content_type.name})
    absurl = get_absolute_url()

    # Try to figure out the object's domain, so we can do a cross-site redirect
    # if necessary.

    # If the object actually defines a domain, we're done.
    if absurl.startswith('http://') or absurl.startswith('https://'):
        return http.HttpResponseRedirect(absurl)

    # Otherwise, we need to introspect the object's relationships for a
    # relation to the Site object
    object_domain = None

    if Site._meta.installed:
        opts = obj._meta

        # First, look for an many-to-many relationship to Site.
        for field in opts.many_to_many:
            if field.rel.to is Site:
                try:
                    # Caveat: In the case of multiple related Sites, this just
                    # selects the *first* one, which is arbitrary.
                    object_domain = getattr(obj, field.name).all()[0].domain
                except IndexError:
                    pass
                if object_domain is not None:
                    break

        # Next, look for a many-to-one relationship to Site.
        if object_domain is None:
            for field in obj._meta.fields:
                if field.rel and field.rel.to is Site:
                    try:
                        object_domain = getattr(obj, field.name).domain
                    except Site.DoesNotExist:
                        pass
                    if object_domain is not None:
                        break

    # Fall back to the current site (if possible).
    if object_domain is None:
        try:
            object_domain = get_current_site(request).domain
        except Site.DoesNotExist:
            pass

    # If all that malarkey found an object domain, use it. Otherwise, fall back
    # to whatever get_absolute_url() returned.
    if object_domain is not None:
        protocol = request.is_secure() and 'https' or 'http'
        return http.HttpResponseRedirect('%s://%s%s'
                                         % (protocol, object_domain, absurl))
    else:
        return http.HttpResponseRedirect(absurl)

и это слишком сложно для меня, чтобы понять.

Когда Django говорит постоянная ссылка, я думаю о наличии ссылки на определенное место на странице (обычно заголовок). Например, документация по структуре комментариев Django - это ссылка № 1, и вы можете сделать постоянную ссылку на раздел «Ссылки на комментарии» со ссылкой № 2.

1. https://docs.djangoproject.com/en/dev/ref/contrib/comments/
2. https://docs.djangoproject.com/en/dev/ref/contrib/comments/#linking-to-comments

Так что за комментарии, не должно ли быть так же? Разве URL не должен быть просто #c1 или что-то без /comments/cr/18/1/...? На самом деле, я даже не знаю, откуда у Джанго 18 и 1 ... Из метода shortcut я понимаю, что 18 - это content_type_id, а 1 - это object_id, но Как я могу определить, какой класс в models.py является идентификатором типа содержимого и идентификатором объекта?

Ответы [ 2 ]

4 голосов
/ 27 марта 2012

Каркас комментариев использует Родовые отношения , чтобы связать Comment объекты с объектами вашей базы данных (модель Order в вашем случае).Общие отношения позволяют одному объекту поддерживать отношения с другим объектом, не зная явно о своем классе.Вы можете увидеть поля, создающие общее отношение (content_type, object_pk, content_object) для комментария здесь: django.contrib.comments.models

После того, как комментарий был сделан и прикреплен к экземпляру определенного класса(например, Order), нам нужен способ получить ссылку на этот конкретный комментарий (постоянная ссылка).Чтобы получить ссылку на комментарий, нам нужно знать URL объекта, к которому был сделан комментарий (опять же, конкретный Order в вашем случае).Это то, что делает get_comment_permalink - он создает URL-адрес для объекта, для которого был оставлен комментарий, а также прикрепляет ссылку-ссылку (часть #c1) к URL-адресу, чтобы браузер переходил к определенному комментарию.эта страница

Чтобы сделать все это, он имеет 3 шага:

  • сначала выясните, с каким типом объекта он имеет дело, просмотрев родовые отношения.Это оставит нас с Order объектом
  • Теперь он пытается получить абсолютный URL get_absolute_url этого объекта.Это может быть / order / my-order /
  • . Эта 'http://mysite.com/' часть URL создается с использованием фреймворка Sites.
  • . Выясняет # c31 (якорная ссылка на комментарий) часть URL

Теперь у нас есть полная http://mysite.com/order/my-order/c#31, которая приведет нас на нужную страницу и покажет правильный комментарий

2 голосов
/ 27 марта 2012

Так что, для комментариев, не должно ли быть то же самое?Разве URL не должен быть просто # c1 или чем-то без / comments / cr / 18/1 / ...?На самом деле, я даже не знаю, откуда у Django 18 и 1 ... Из метода ярлыков я понимаю, что 18 - это content_type_id, а 1 - это

18 - это идентификатор типа контента, и1 - это идентификатор объекта.В контекстном представлении объект выбирается из базы данных с использованием этих параметров и перенаправляется на modelobject.get_absolute_url().

Определите / исправьте метод get_absolute_url () в ваших моделях , это восстановит django.contrib.contenttypes.views.shortcut.

Тем не менее, Django ожидает, что URL объекта модели отображает список комментариев для этого объекта.В этом случае просто добавьте <a name="c{{ comment.id }}"></a> в свой HTML-комментарий.

...