don t use the manager to ensure the site exists with pk1 regardless of whether or not it already exists can view a shortcut when object s getabsoluteurl returns a full url the tested urls are http https and shortcuts for an object that has no getabsoluteurl method raise 404 the shortcut view works if a model s foreignkey to site is none when the object has a manytomanyfield to site redirect to the current site if it s attached to the object or to the domain of the first site found in the m2m relationship getcurrentsite will lookup a site object so these must match the domains in the mocksite model redirects to the domain of the first site found in the m2m relationship ordering is arbitrary redirects to the domain of the site matching the current site s domain redirects to the domain of the site matching the request s host header the view returns a complete url regardless of whether the sites framework is installed the view returns 404 when model getabsoluteurl isn t defined userct contenttype objects getformodelfoowithouturl obj foowithouturl objects createnamejohn with self assertraiseshttp404 shortcutself request userct id obj id def testmodelwithbrokengetabsoluteurlself userct contenttype objects getformodelfoowithbrokenabsoluteurl obj foowithbrokenabsoluteurl objects createnamejohn with self assertraisesattributeerror shortcutself request userct id obj id don t use the manager to ensure the site exists with pk 1 regardless of whether or not it already exists can view a shortcut when object s get_absolute_url returns a full url the tested urls are http https and shortcuts for an object that has no get_absolute_url method raise 404 the shortcut view works if a model s foreignkey to site is none when the object has a manytomanyfield to site redirect to the current site if it s attached to the object or to the domain of the first site found in the m2m relationship get_current_site will lookup a site object so these must match the domains in the mocksite model redirects to the domain of the first site found in the m2m relationship ordering is arbitrary redirects to the domain of the site matching the current site s domain redirects to the domain of the site matching the request s host header the view returns a complete url regardless of whether the sites framework is installed the view returns 404 when model get_absolute_url isn t defined the view doesn t catch an attributeerror raised by model get_absolute_url 8997
import datetime
from unittest import mock

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.views import shortcut
from django.contrib.sites.models import Site
from django.contrib.sites.shortcuts import get_current_site
from django.http import Http404, HttpRequest
from django.test import TestCase, override_settings

from .models import (
    Article,
    Author,
    FooWithBrokenAbsoluteUrl,
    FooWithoutUrl,
    FooWithUrl,
    ModelWithM2MToSite,
    ModelWithNullFKToSite,
    SchemeIncludedURL,
)
from .models import Site as MockSite


@override_settings(ROOT_URLCONF="contenttypes_tests.urls")
class ContentTypesViewsTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        
        
        cls.site1 = Site(pk=1, domain="testserver", name="testserver")
        cls.site1.save()
        cls.author1 = Author.objects.create(name="Boris")
        cls.article1 = Article.objects.create(
            title="Old Article",
            slug="old_article",
            author=cls.author1,
            date_created=datetime.datetime(2001, 1, 1, 21, 22, 23),
        )
        cls.article2 = Article.objects.create(
            title="Current Article",
            slug="current_article",
            author=cls.author1,
            date_created=datetime.datetime(2007, 9, 17, 21, 22, 23),
        )
        cls.article3 = Article.objects.create(
            title="Future Article",
            slug="future_article",
            author=cls.author1,
            date_created=datetime.datetime(3000, 1, 1, 21, 22, 23),
        )
        cls.scheme1 = SchemeIncludedURL.objects.create(
            url="http://test_scheme_included_http/"
        )
        cls.scheme2 = SchemeIncludedURL.objects.create(
            url="https://test_scheme_included_https/"
        )
        cls.scheme3 = SchemeIncludedURL.objects.create(
            url="//test_default_scheme_kept/"
        )

    def setUp(self):
        Site.objects.clear_cache()

    def test_shortcut_with_absolute_url(self):
        "Can view a shortcut for an Author object that has a get_absolute_url method"
        for obj in Author.objects.all():
            with self.subTest(obj=obj):
                short_url = "/shortcut/%s/%s/" % (
                    ContentType.objects.get_for_model(Author).id,
                    obj.pk,
                )
                response = self.client.get(short_url)
                self.assertRedirects(
                    response,
                    "http://testserver%s" % obj.get_absolute_url(),
                    target_status_code=404,
                )

    def test_shortcut_with_absolute_url_including_scheme(self):
        
        for obj in SchemeIncludedURL.objects.all():
            with self.subTest(obj=obj):
                short_url = "/shortcut/%s/%s/" % (
                    ContentType.objects.get_for_model(SchemeIncludedURL).id,
                    obj.pk,
                )
                response = self.client.get(short_url)
                self.assertRedirects(
                    response, obj.get_absolute_url(), fetch_redirect_response=False
                )

    def test_shortcut_no_absolute_url(self):
        
        for obj in Article.objects.all():
            with self.subTest(obj=obj):
                short_url = "/shortcut/%s/%s/" % (
                    ContentType.objects.get_for_model(Article).id,
                    obj.pk,
                )
                response = self.client.get(short_url)
                self.assertEqual(response.status_code, 404)

    def test_wrong_type_pk(self):
        short_url = "/shortcut/%s/%s/" % (
            ContentType.objects.get_for_model(Author).id,
            "nobody/expects",
        )
        response = self.client.get(short_url)
        self.assertEqual(response.status_code, 404)

    def test_shortcut_bad_pk(self):
        short_url = "/shortcut/%s/%s/" % (
            ContentType.objects.get_for_model(Author).id,
            "42424242",
        )
        response = self.client.get(short_url)
        self.assertEqual(response.status_code, 404)

    def test_nonint_content_type(self):
        an_author = Author.objects.all()[0]
        short_url = "/shortcut/%s/%s/" % ("spam", an_author.pk)
        response = self.client.get(short_url)
        self.assertEqual(response.status_code, 404)

    def test_bad_content_type(self):
        an_author = Author.objects.all()[0]
        short_url = "/shortcut/%s/%s/" % (42424242, an_author.pk)
        response = self.client.get(short_url)
        self.assertEqual(response.status_code, 404)


@override_settings(ROOT_URLCONF="contenttypes_tests.urls")
class ContentTypesViewsSiteRelTests(TestCase):
    def setUp(self):
        Site.objects.clear_cache()

    @classmethod
    def setUpTestData(cls):
        cls.site_2 = Site.objects.create(domain="example2.com", name="example2.com")
        cls.site_3 = Site.objects.create(domain="example3.com", name="example3.com")

    @mock.patch("django.apps.apps.get_model")
    def test_shortcut_view_with_null_site_fk(self, get_model):
        
        get_model.side_effect = (
            lambda *args, **kwargs: MockSite
            if args[0] == "sites.Site"
            else ModelWithNullFKToSite
        )

        obj = ModelWithNullFKToSite.objects.create(title="title")
        url = "/shortcut/%s/%s/" % (
            ContentType.objects.get_for_model(ModelWithNullFKToSite).id,
            obj.pk,
        )
        response = self.client.get(url)
        expected_url = "http://example.com%s" % obj.get_absolute_url()
        self.assertRedirects(response, expected_url, fetch_redirect_response=False)

    @mock.patch("django.apps.apps.get_model")
    def test_shortcut_view_with_site_m2m(self, get_model):
        
        get_model.side_effect = (
            lambda *args, **kwargs: MockSite
            if args[0] == "sites.Site"
            else ModelWithM2MToSite
        )

        
        
        MockSite.objects.bulk_create(
            [
                MockSite(pk=1, domain="example.com"),
                MockSite(pk=self.site_2.pk, domain=self.site_2.domain),
                MockSite(pk=self.site_3.pk, domain=self.site_3.domain),
            ]
        )
        ct = ContentType.objects.get_for_model(ModelWithM2MToSite)
        site_3_obj = ModelWithM2MToSite.objects.create(
            title="Not Linked to Current Site"
        )
        site_3_obj.sites.add(MockSite.objects.get(pk=self.site_3.pk))
        expected_url = "http://%s%s" % (
            self.site_3.domain,
            site_3_obj.get_absolute_url(),
        )

        with self.settings(SITE_ID=self.site_2.pk):
            
            
            response = self.client.get("/shortcut/%s/%s/" % (ct.pk, site_3_obj.pk))
            self.assertRedirects(response, expected_url, fetch_redirect_response=False)

        obj_with_sites = ModelWithM2MToSite.objects.create(
            title="Linked to Current Site"
        )
        obj_with_sites.sites.set(MockSite.objects.all())
        shortcut_url = "/shortcut/%s/%s/" % (ct.pk, obj_with_sites.pk)
        expected_url = "http://%s%s" % (
            self.site_2.domain,
            obj_with_sites.get_absolute_url(),
        )

        with self.settings(SITE_ID=self.site_2.pk):
            
            
            response = self.client.get(shortcut_url)
            self.assertRedirects(response, expected_url, fetch_redirect_response=False)

        with self.settings(SITE_ID=None, ALLOWED_HOSTS=[self.site_2.domain]):
            
            
            response = self.client.get(shortcut_url, SERVER_NAME=self.site_2.domain)
            self.assertRedirects(response, expected_url, fetch_redirect_response=False)


class ShortcutViewTests(TestCase):
    def setUp(self):
        self.request = HttpRequest()
        self.request.META = {"SERVER_NAME": "Example.com", "SERVER_PORT": "80"}

    @override_settings(ALLOWED_HOSTS=["example.com"])
    def test_not_dependent_on_sites_app(self):
        
        user_ct = ContentType.objects.get_for_model(FooWithUrl)
        obj = FooWithUrl.objects.create(name="john")
        with self.modify_settings(INSTALLED_APPS={"append": "django.contrib.sites"}):
            response = shortcut(self.request, user_ct.id, obj.id)
            self.assertEqual(
                "http://%s/users/john/" % get_current_site(self.request).domain,
                response.headers.get("location"),
            )
        with self.modify_settings(INSTALLED_APPS={"remove": "django.contrib.sites"}):
            response = shortcut(self.request, user_ct.id, obj.id)
            self.assertEqual(
                "http://Example.com/users/john/", response.headers.get("location")
            )

    def test_model_without_get_absolute_url(self):
        
        user_ct = ContentType.objects.get_for_model(FooWithoutUrl)
        obj = FooWithoutUrl.objects.create(name="john")
        with self.assertRaises(Http404):
            shortcut(self.request, user_ct.id, obj.id)

    def test_model_with_broken_get_absolute_url(self):
        
        user_ct = ContentType.objects.get_for_model(FooWithBrokenAbsoluteUrl)
        obj = FooWithBrokenAbsoluteUrl.objects.create(name="john")
        with self.assertRaises(AttributeError):
            shortcut(self.request, user_ct.id, obj.id)