app/django/contrib/contenttypes/views.py
author Mario Ferraro <fadinlight@gmail.com>
Sun, 15 Nov 2009 22:12:20 +0100
changeset 3093 d1be59b6b627
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
GMaps related JS changed to use new google namespace. Google is going to change permanently in the future the way to load its services, so better stay safe. Also this commit shows uses of the new melange.js module. Fixes Issue 634.

from django import http
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist

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)
        obj = content_type.get_object_for_this_type(pk=object_id)
    except ObjectDoesNotExist:
        raise http.Http404("Content type %s object %s doesn't exist" % (content_type_id, object_id))
    try:
        absurl = obj.get_absolute_url()
    except AttributeError:
        raise http.Http404("%s objects don't have get_absolute_url() methods" % content_type.name)

    # 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
    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 = Site.objects.get_current().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)