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