How does get_comment_permalink work in Django's comment structure?

I don't really understand get_comment_permalink

about Django's comment framework.

I created some comments for my class Order

using Django comments, by default it shows a url of something like /comments/cr/18/1/#c1

and that url never exists.

I looked at the comment urls.py

and it has a line that says

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

      

views.py

which has a method 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 page based on a content-type ID and an object ID.
    """
    # Look up the object, making sure it 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 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 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)

      

and it's too hard for me to understand.

When Django says permalink, I think of a link to a specific location on the page (usually the title). For example, the Django comment docs documentation is link # 1 and you can move the "Link to comments" link with link # 2.

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

      

So it shouldn't be the same for comments? Should the url be simple #c1

or something without /comments/cr/18/1/...

? Actually I don't even know where Django got 18

and 1

... From the method shortcut

I understand what 18

is content_type_id

and 1

is object_id

, but how can I determine which class in models.py

is the content type id and object id?

+3


source to share


2 answers


So it shouldn't be the same for comments? Shouldn't the URL just be # c1 or something without / comments / cr / 18/1 / ...? In fact, I don't even know where Django got 18 and 1 ... From the shortcuts method I understand that 18 is the content_type_id and 1 is

18 is the content type identifier and 1 is the object identifier. The hidden view fetches the object from the database using these parameters and redirects to modelobject.get_absolute_url()

.



Define / fix the get_absolute_url () method in your models , this will restore django.contrib.contenttypes.views.shortcut

.

However, Django expects the URL of a model object to display a list of comments for that object. In this case, just add <a name="c{{ comment.id }}"></a>

HTML to your comment.

+2


source


The comment structure uses Shared Relations to bind objects Comment

to database objects ( Order

model in your case). Shared relationships allow one object to communicate with another object without knowing about the class. You can see the fields creating general relationships (content_type, object_pk, content_object) for comments here:django.contrib.comments.models

Once a comment has been made and attached to an instance of a specific class (like one Order

), we need a way to get a link to that specific comment (permalink). To get a link to a comment, we need to know the URL of the object the comment was made on (again, specific Order

in your case). This is what it does get_comment_permalink

- it constructs the url of the object for which the comment was made, and also binds an anchor link (part #c1

) to the url so that the browser navigates to the specific comment on that page.

To do all this, you have 3 steps:



  • first figure out what type of object it encounters by looking at the general relationship. This will leave us with an objectOrder

  • Now it tries to get the absolute URL of get_absolute_url

    this object. It could be / order / my -order /
  • It constructs the `http://mysite.com/'URL portion using the site infrastructure
  • It renders link # c31 (comment anchor link) part of url

We now have the complete http://mysite.com/order/my-order/c#31 which will take us to the correct page and show the correct comment

+4


source







All Articles