3

我不太了解get_comment_permalinkDjango 的评论框架。

我使用 Django 的评论为我的班级创建了一些评论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.pyshortcut方法的是

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 不应该只是 a#c1或没有 的东西/comments/cr/18/1/...吗?实际上我什至不知道 Django 从哪里得到18and 1... 从shortcut方法中,我知道18content_type_idand1object_id,但是我怎么知道哪个类models.py是哪个内容类型 id 和对象 id?

4

2 回答 2

4

评论框架使用通用关系Comment对象链接到您的数据库对象(Order在您的情况下为模型)。通用关系允许一个对象在不明确知道它的类的情况下与另一个对象保持关系。您可以在此处查看创建通用关系(content_type、object_pk、content_object)的字段以供评论:django.contrib.comments.models

一旦发表评论并将其附加到特定类的实例(例如单个Order),我们需要一种方法来获取指向该特定评论的链接(永久链接)。要获得评论的链接,我们需要知道评论所针对的对象的 URL(同样,Order在您的情况下是特定的)。这就是get_comment_permalink正在做的事情 - 它构造一个指向已留下评论的对象的 URL,并将锚链接(#c1部分)附加到 URL,以便浏览器跳转到该页面上的特定评论。

要做到这一切,它有 3 个步骤:

  • 首先通过查找通用关系找出它正在处理的对象类型。这会给我们留下一个Order对象
  • 现在它尝试获取该get_absolute_url对象的绝对 url。这可能是 /order/my-order/
  • 它使用站点框架构造 URL 的“http://mysite.com/”部分
  • 它计算出 url 的 #c31 (评论的锚链接)部分

现在我们有一个完整的http://mysite.com/order/my-order/c#31将把我们带到正确的页面并显示正确的评论

于 2012-03-27T08:58:13.977 回答
2

所以对于评论,不应该是一样的吗?URL 不应该只是一个 #c1 或没有 /comments/cr/18/1/... 的东西吗?事实上我什至不知道 Django 从哪里得到 18 和 1... 从快捷方式中,我知道 18 是 content_type_id 而 1 是

18 是内容类型 ID,1 是对象 ID。快捷视图使用这些参数从数据库中获取对象并重定向到modelobject.get_absolute_url().

在模型中定义/修复 get_absolute_url() 方法,这将修复django.contrib.contenttypes.views.shortcut

也就是说,Django 期望模型对象的 url 显示该对象的评论列表。在这种情况下,只需添加<a name="c{{ comment.id }}"></a>您的单个评论 HTML。

于 2012-03-27T08:56:00.567 回答