You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

views.py 3.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from django.apps import apps
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.contrib.sites.shortcuts import get_current_site
  4. from django.core.exceptions import ObjectDoesNotExist
  5. from django.http import Http404, HttpResponseRedirect
  6. from django.utils.translation import gettext as _
  7. def shortcut(request, content_type_id, object_id):
  8. """
  9. Redirect to an object's page based on a content-type ID and an object ID.
  10. """
  11. # Look up the object, making sure it's got a get_absolute_url() function.
  12. try:
  13. content_type = ContentType.objects.get(pk=content_type_id)
  14. if not content_type.model_class():
  15. raise Http404(
  16. _("Content type %(ct_id)s object has no associated model") %
  17. {'ct_id': content_type_id}
  18. )
  19. obj = content_type.get_object_for_this_type(pk=object_id)
  20. except (ObjectDoesNotExist, ValueError):
  21. raise Http404(
  22. _("Content type %(ct_id)s object %(obj_id)s doesn't exist") %
  23. {'ct_id': content_type_id, 'obj_id': object_id}
  24. )
  25. try:
  26. get_absolute_url = obj.get_absolute_url
  27. except AttributeError:
  28. raise Http404(
  29. _("%(ct_name)s objects don't have a get_absolute_url() method") %
  30. {'ct_name': content_type.name}
  31. )
  32. absurl = get_absolute_url()
  33. # Try to figure out the object's domain, so we can do a cross-site redirect
  34. # if necessary.
  35. # If the object actually defines a domain, we're done.
  36. if absurl.startswith(('http://', 'https://', '//')):
  37. return HttpResponseRedirect(absurl)
  38. # Otherwise, we need to introspect the object's relationships for a
  39. # relation to the Site object
  40. try:
  41. object_domain = get_current_site(request).domain
  42. except ObjectDoesNotExist:
  43. object_domain = None
  44. if apps.is_installed('django.contrib.sites'):
  45. Site = apps.get_model('sites.Site')
  46. opts = obj._meta
  47. for field in opts.many_to_many:
  48. # Look for a many-to-many relationship to Site.
  49. if field.remote_field.model is Site:
  50. site_qs = getattr(obj, field.name).all()
  51. if object_domain and site_qs.filter(domain=object_domain).exists():
  52. # The current site's domain matches a site attached to the
  53. # object.
  54. break
  55. # Caveat: In the case of multiple related Sites, this just
  56. # selects the *first* one, which is arbitrary.
  57. site = site_qs.first()
  58. if site:
  59. object_domain = site.domain
  60. break
  61. else:
  62. # No many-to-many relationship to Site found. Look for a
  63. # many-to-one relationship to Site.
  64. for field in obj._meta.fields:
  65. if field.remote_field and field.remote_field.model is Site:
  66. try:
  67. site = getattr(obj, field.name)
  68. except Site.DoesNotExist:
  69. continue
  70. if site is not None:
  71. object_domain = site.domain
  72. break
  73. # If all that malarkey found an object domain, use it. Otherwise, fall back
  74. # to whatever get_absolute_url() returned.
  75. if object_domain is not None:
  76. protocol = request.scheme
  77. return HttpResponseRedirect('%s://%s%s' % (protocol, object_domain, absurl))
  78. else:
  79. return HttpResponseRedirect(absurl)