app/django/contrib/contenttypes/views.py
author Sverre Rabbelier <srabbelier@gmail.com>
Sun, 07 Dec 2008 17:02:10 +0000
changeset 705 0ab17e14df95
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
Move document sidebar entries extraction to document.View This way other modules can benefit from the same logic. Also make use of the sidebar.getSidebarMenu method so that getMenusForScope is no longer specific to full menu's. Patch by: Sverre Rabbelier

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)