[1.7.x] Fixed #22994 -- regression with generic FK + admin list_view

The reason for the regression was that the GenericForeignKey field isn't
something meta.get_field_by_name() should return. The reason is that a
couple of places in Django expects get_field_by_name() to work this way.
It could make sense to return GFKs from get_field_by_name(), but that
should likely be done as part of meta refactoring or virtual fields
refactoring patches.

Thanks to glicerinu@gmail.com for the report and to Tim for working on
the issue.
This commit is contained in:
Anssi Kääriäinen 2014-07-14 12:50:41 -04:00 committed by Tim Graham
parent 1d1debeed4
commit 572885729e
3 changed files with 25 additions and 3 deletions

View File

@ -451,7 +451,9 @@ class Options(object):
for f, model in self.get_fields_with_model(): for f, model in self.get_fields_with_model():
cache[f.name] = cache[f.attname] = (f, model, True, False) cache[f.name] = cache[f.attname] = (f, model, True, False)
for f in self.virtual_fields: for f in self.virtual_fields:
cache[f.name] = (f, None if f.model == self.model else f.model, True, False) if hasattr(f, 'related'):
cache[f.name] = cache[f.attname] = (
f, None if f.model == self.model else f.model, True, False)
if apps.ready: if apps.ready:
self._name_map = cache self._name_map = cache
return cache return cache

View File

@ -35,7 +35,7 @@ from .models import (Article, Chapter, Child, Parent, Picture, Widget,
UnchangeableObject, UserMessenger, Simple, Choice, ShortMessage, Telegram, UnchangeableObject, UserMessenger, Simple, Choice, ShortMessage, Telegram,
FilteredManager, EmptyModelHidden, EmptyModelVisible, EmptyModelMixin, FilteredManager, EmptyModelHidden, EmptyModelVisible, EmptyModelMixin,
State, City, Restaurant, Worker, ParentWithDependentChildren, State, City, Restaurant, Worker, ParentWithDependentChildren,
DependentChild, StumpJoke, FieldOverridePost) DependentChild, StumpJoke, FieldOverridePost, FunkyTag)
def callable_year(dt_value): def callable_year(dt_value):
@ -821,6 +821,10 @@ class RestaurantAdmin(admin.ModelAdmin):
return {'name': 'overridden_value'} return {'name': 'overridden_value'}
class FunkyTagAdmin(admin.ModelAdmin):
list_display = ('name', 'content_object')
site = admin.AdminSite(name="admin") site = admin.AdminSite(name="admin")
site.register(Article, ArticleAdmin) site.register(Article, ArticleAdmin)
site.register(CustomArticle, CustomArticleAdmin) site.register(CustomArticle, CustomArticleAdmin)
@ -876,6 +880,7 @@ site.register(State, StateAdmin)
site.register(City, CityAdmin) site.register(City, CityAdmin)
site.register(Restaurant, RestaurantAdmin) site.register(Restaurant, RestaurantAdmin)
site.register(Worker, WorkerAdmin) site.register(Worker, WorkerAdmin)
site.register(FunkyTag, FunkyTagAdmin)
# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
# That way we cover all four cases: # That way we cover all four cases:

View File

@ -1655,11 +1655,26 @@ class AdminViewDeletedObjectsTest(TestCase):
""" """
plot = Plot.objects.get(pk=3) plot = Plot.objects.get(pk=3)
FunkyTag.objects.create(content_object=plot, name='hott') FunkyTag.objects.create(content_object=plot, name='hott')
should_contain = """<li>Funky tag: hott""" should_contain = """<li>Funky tag: <a href="/test_admin/admin/admin_views/funkytag/1/">hott"""
response = self.client.get('/test_admin/admin/admin_views/plot/%s/delete/' % quote(3)) response = self.client.get('/test_admin/admin/admin_views/plot/%s/delete/' % quote(3))
self.assertContains(response, should_contain) self.assertContains(response, should_contain)
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class TestGenericRelations(TestCase):
urls = "admin_views.urls"
fixtures = ['admin-views-users.xml', 'deleted-objects.xml']
def setUp(self):
self.client.login(username='super', password='secret')
def test_generic_content_object_in_list_display(self):
plot = Plot.objects.get(pk=3)
FunkyTag.objects.create(content_object=plot, name='hott')
response = self.client.get('/test_admin/admin/admin_views/funkytag/')
self.assertContains(response, "%s</td>" % plot)
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class AdminViewStringPrimaryKeyTest(TestCase): class AdminViewStringPrimaryKeyTest(TestCase):
urls = "admin_views.urls" urls = "admin_views.urls"