2012-03-27 59 views
3

我並不十分了解Django的評論框架中的get_comment_permalinkDjango評論框架中的get_comment_permalink如何工作?

我使用Django的評論爲我的課Order創建了一些評論,默認情況下它顯示類似/comments/cr/18/1/#c1的url,並且該url永遠不存在。

我看了看評論的urls.py,它有這樣一行

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

它具有shortcutviews.py

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 

所以對於評論,不應該是相同的嗎?不應該只是簡單的#c1或沒有/comments/cr/18/1/...的東西?事實上,我甚至不知道從哪裏得到的Django和18 ... 1shortcut方法,據我所知,18content_type_id1object_id,但我怎麼能知道哪些類models.py是內容類型ID和對象ID?

回答

2

所以對於評論,不應該是相同的嗎? URL不應該只是#c1或沒有/ comments/cr/18/1/...的東西?事實上,我甚至不知道Django在哪裏得到了18和1 ...從快捷方法中,我瞭解到18是content_type_id,1是

18是內容類型標識,1是對象ID。快捷視圖使用這些參數從數據庫中提取對象,並重定向到modelobject.get_absolute_url()

定義/修復模型中的get_absolute_url()方法,這將修復django.contrib.contenttypes.views.shortcut。也就是說,Django期望模型對象的url顯示這個對象的註釋列表。在這種情況下,只需在您的單個評論HTML中添加<a name="c{{ comment.id }}"></a>即可。

+0

不這似乎違背DRY pinciple /鬆耦合?我在'models.py'中定義了'def get_absolute_url(self):return「/ doors/orders/{pk} /」.format(pk = self.pk)'並且定義了'r'^ orders /(?P我的門應用程序中的'urls.py'中的 \ d +)/ $''(完整路徑仍然是'/ doors/orders/1 /'之類的東西)。有沒有辦法「倒退」或「reverse_lazy」呢? – hobbes3 2012-03-27 20:27:21

+1

這是另一個問題,所以我會簡短介紹一下,但是,你是對的!你應該做這樣的事情來獲取url:'from django.core import urlresolvers; urlresolvers.reverse('doors_order_detail',args = [self.pk])'。當然,這需要您[命名您的訂單明細網址](https://docs.djangoproject.com/en/dev/topics/http/urls/#id2)'doors_order_detail',這在Django中非常標準。 – jpic 2012-03-27 20:32:05

4

評論框架使用Generic RelationsComment對象鏈接到您的數據庫對象(您的案例中的Order模型)。通用關係允許一個對象與另一個對象保持關係,而不必明確知道它的類。你可以看到創建評論這裏的一般關係(CONTENT_TYPE,object_pk,content_object)領域:django.contrib.comments.models

一旦評論已取得並連接到特定的類的實例(單Order例如),我們需要一種獲取特定評論鏈接的方式(固定鏈接)。要獲得評論的鏈接,我們需要知道評論所在的對象的URL(同樣,您的案例中的特定Order)。這就是get_comment_permalink正在執行的操作 - 它爲已留下注釋的對象構造一個URL,並將URL鏈接(#c1部分)附加到該URL,以便瀏覽器跳轉到該頁面上的特定註釋。

要做到這一切有3個步驟:

  • 首先要弄清楚什麼類型的對象它是通過查找通用的關係處理。這會給我們留下一個Order對象
  • 現在,它嘗試獲取該對象的絕對URL get_absolute_url。這可能是/ order/my-order/
  • 它通過使用站點框架構建URL的'http://mysite.com/'部分
  • 它計算出#c31(到評論的錨鏈接網址

現在,我們有充分的http://mysite.com/order/my-order/c#31,將我們帶到正確的頁面,並顯示正確的註釋)的一部分

+0

感謝關於通用關係的解釋! – hobbes3 2012-03-27 20:52:53