app/django/contrib/contenttypes/views.py
changeset 323 ff1a9aa48cfd
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
       
     1 from django import http
       
     2 from django.contrib.contenttypes.models import ContentType
       
     3 from django.contrib.sites.models import Site
       
     4 from django.core.exceptions import ObjectDoesNotExist
       
     5 
       
     6 def shortcut(request, content_type_id, object_id):
       
     7     "Redirect to an object's page based on a content-type ID and an object ID."
       
     8     # Look up the object, making sure it's got a get_absolute_url() function.
       
     9     try:
       
    10         content_type = ContentType.objects.get(pk=content_type_id)
       
    11         obj = content_type.get_object_for_this_type(pk=object_id)
       
    12     except ObjectDoesNotExist:
       
    13         raise http.Http404("Content type %s object %s doesn't exist" % (content_type_id, object_id))
       
    14     try:
       
    15         absurl = obj.get_absolute_url()
       
    16     except AttributeError:
       
    17         raise http.Http404("%s objects don't have get_absolute_url() methods" % content_type.name)
       
    18 
       
    19     # Try to figure out the object's domain, so we can do a cross-site redirect
       
    20     # if necessary.
       
    21 
       
    22     # If the object actually defines a domain, we're done.
       
    23     if absurl.startswith('http://') or absurl.startswith('https://'):
       
    24         return http.HttpResponseRedirect(absurl)
       
    25 
       
    26     # Otherwise, we need to introspect the object's relationships for a
       
    27     # relation to the Site object
       
    28     object_domain = None
       
    29     opts = obj._meta
       
    30 
       
    31     # First, look for an many-to-many relationship to Site.
       
    32     for field in opts.many_to_many:
       
    33         if field.rel.to is Site:
       
    34             try:
       
    35                 # Caveat: In the case of multiple related Sites, this just
       
    36                 # selects the *first* one, which is arbitrary.
       
    37                 object_domain = getattr(obj, field.name).all()[0].domain
       
    38             except IndexError:
       
    39                 pass
       
    40             if object_domain is not None:
       
    41                 break
       
    42 
       
    43     # Next, look for a many-to-one relationship to Site.
       
    44     if object_domain is None:
       
    45         for field in obj._meta.fields:
       
    46             if field.rel and field.rel.to is Site:
       
    47                 try:
       
    48                     object_domain = getattr(obj, field.name).domain
       
    49                 except Site.DoesNotExist:
       
    50                     pass
       
    51                 if object_domain is not None:
       
    52                     break
       
    53 
       
    54     # Fall back to the current site (if possible).
       
    55     if object_domain is None:
       
    56         try:
       
    57             object_domain = Site.objects.get_current().domain
       
    58         except Site.DoesNotExist:
       
    59             pass
       
    60 
       
    61     # If all that malarkey found an object domain, use it. Otherwise, fall back
       
    62     # to whatever get_absolute_url() returned.
       
    63     if object_domain is not None:
       
    64         protocol = request.is_secure() and 'https' or 'http'
       
    65         return http.HttpResponseRedirect('%s://%s%s' % (protocol, object_domain, absurl))
       
    66     else:
       
    67         return http.HttpResponseRedirect(absurl)