[3.1.x] Fixed #32038 -- Fixed EmptyFieldListFilter crash with GenericRelation.

Thanks Javier Matos Odut for the report.

Backport of e4ab44a4b2 from master
This commit is contained in:
Mariusz Felisiak 2020-09-24 09:45:51 +02:00
parent 986cd28f95
commit b7df7de44f
3 changed files with 33 additions and 0 deletions

View File

@ -277,6 +277,7 @@ class GenericRelation(ForeignObject):
# Field flags # Field flags
auto_created = False auto_created = False
empty_strings_allowed = False
many_to_many = False many_to_many = False
many_to_one = False many_to_one = False
@ -295,6 +296,9 @@ class GenericRelation(ForeignObject):
limit_choices_to=limit_choices_to, limit_choices_to=limit_choices_to,
) )
# Reverse relations are always nullable (Django can't enforce that a
# foreign key on the related model points to this model).
kwargs['null'] = True
kwargs['blank'] = True kwargs['blank'] = True
kwargs['on_delete'] = models.CASCADE kwargs['on_delete'] = models.CASCADE
kwargs['editable'] = False kwargs['editable'] = False

View File

@ -23,3 +23,6 @@ Bugfixes
* Fixed a bug in Django 3.1 where a test database was not synced during * Fixed a bug in Django 3.1 where a test database was not synced during
creation when using the :setting:`MIGRATE <TEST_MIGRATE>` test database creation when using the :setting:`MIGRATE <TEST_MIGRATE>` test database
setting (:ticket:`32012`). setting (:ticket:`32012`).
* Fixed a ``django.contrib.admin.EmptyFieldListFilter`` crash when using on a
``GenericRelation`` (:ticket:`32038`).

View File

@ -1477,6 +1477,32 @@ class ListFiltersTests(TestCase):
queryset = changelist.get_queryset(request) queryset = changelist.get_queryset(request)
self.assertCountEqual(queryset, expected_result) self.assertCountEqual(queryset, expected_result)
def test_emptylistfieldfilter_genericrelation(self):
class BookmarkGenericRelation(ModelAdmin):
list_filter = (
('tags', EmptyFieldListFilter),
)
modeladmin = BookmarkGenericRelation(Bookmark, site)
django_bookmark = Bookmark.objects.create(url='https://www.djangoproject.com/')
python_bookmark = Bookmark.objects.create(url='https://www.python.org/')
none_tags = Bookmark.objects.create(url='https://www.kernel.org/')
TaggedItem.objects.create(content_object=django_bookmark, tag='python')
TaggedItem.objects.create(content_object=python_bookmark, tag='python')
tests = [
({'tags__isempty': '1'}, [none_tags]),
({'tags__isempty': '0'}, [django_bookmark, python_bookmark]),
]
for query_string, expected_result in tests:
with self.subTest(query_string=query_string):
request = self.request_factory.get('/', query_string)
request.user = self.alfred
changelist = modeladmin.get_changelist_instance(request)
queryset = changelist.get_queryset(request)
self.assertCountEqual(queryset, expected_result)
def test_emptylistfieldfilter_choices(self): def test_emptylistfieldfilter_choices(self):
modeladmin = BookAdminWithEmptyFieldListFilter(Book, site) modeladmin = BookAdminWithEmptyFieldListFilter(Book, site)
request = self.request_factory.get('/') request = self.request_factory.get('/')