Kaydet (Commit) d29d11b0 authored tarafından dani poni's avatar dani poni Kaydeden (comit) Tim Graham

Fixed #26085 -- Fixed contenttypes shortcut() view crash with a null fk to Site.

Thanks Fabien Schwob for the initial patch.
üst e494b9ff
...@@ -63,9 +63,11 @@ def shortcut(request, content_type_id, object_id): ...@@ -63,9 +63,11 @@ def shortcut(request, content_type_id, object_id):
for field in obj._meta.fields: for field in obj._meta.fields:
if field.remote_field and field.remote_field.model is Site: if field.remote_field and field.remote_field.model is Site:
try: try:
object_domain = getattr(obj, field.name).domain site = getattr(obj, field.name)
except Site.DoesNotExist: except Site.DoesNotExist:
pass continue
if site is not None:
object_domain = site.domain
if object_domain is not None: if object_domain is not None:
break break
......
...@@ -4,11 +4,21 @@ from django.contrib.contenttypes.fields import ( ...@@ -4,11 +4,21 @@ from django.contrib.contenttypes.fields import (
GenericForeignKey, GenericRelation, GenericForeignKey, GenericRelation,
) )
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import SiteManager
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.http import urlquote from django.utils.http import urlquote
@python_2_unicode_compatible
class Site(models.Model):
domain = models.CharField(max_length=100)
objects = SiteManager()
def __str__(self):
return self.domain
@python_2_unicode_compatible @python_2_unicode_compatible
class Author(models.Model): class Author(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
...@@ -115,3 +125,15 @@ class Post(models.Model): ...@@ -115,3 +125,15 @@ class Post(models.Model):
def __str__(self): def __str__(self):
return self.title return self.title
@python_2_unicode_compatible
class ModelWithNullFKToSite(models.Model):
title = models.CharField(max_length=200)
site = models.ForeignKey(Site, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return '/title/%s/' % urlquote(self.title)
...@@ -12,11 +12,14 @@ from django.contrib.contenttypes.models import ContentType ...@@ -12,11 +12,14 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core import checks from django.core import checks
from django.db import connections, models from django.db import connections, models
from django.test import SimpleTestCase, TestCase, override_settings from django.test import SimpleTestCase, TestCase, mock, override_settings
from django.test.utils import captured_stdout, isolate_apps from django.test.utils import captured_stdout, isolate_apps
from django.utils.encoding import force_str, force_text from django.utils.encoding import force_str, force_text
from .models import Article, Author, SchemeIncludedURL from .models import (
Article, Author, ModelWithNullFKToSite, SchemeIncludedURL,
Site as MockSite,
)
@override_settings(ROOT_URLCONF='contenttypes_tests.urls') @override_settings(ROOT_URLCONF='contenttypes_tests.urls')
...@@ -94,6 +97,21 @@ class ContentTypesViewsTests(TestCase): ...@@ -94,6 +97,21 @@ class ContentTypesViewsTests(TestCase):
response = self.client.get(short_url) response = self.client.get(short_url)
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@mock.patch('django.apps.apps.get_model')
def test_shortcut_view_with_null_site_fk(self, get_model):
"""
The shortcut view works if a model's ForeignKey to site is None.
"""
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)
self.assertRedirects(
response, '%s' % obj.get_absolute_url(),
fetch_redirect_response=False,
)
def test_create_contenttype_on_the_spot(self): def test_create_contenttype_on_the_spot(self):
""" """
Make sure ContentTypeManager.get_for_model creates the corresponding Make sure ContentTypeManager.get_for_model creates the corresponding
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment