/django/contrib/contenttypes/views.py

https://code.google.com/p/mango-py/ · Python · 71 lines · 49 code · 9 blank · 13 comment · 27 complexity · deeda1cbd920ee0e6c95d200f7f1d31f MD5 · raw file

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