[3.2.x] Fixed #32649 -- Fixed ModelAdmin.search_fields crash when searching against phrases with unbalanced quotes.

Thanks Dlis for the report.

Regression in 26a413507a.
Backport of 23fa29f6a6 from main
This commit is contained in:
Mariusz Felisiak 2021-04-14 12:23:47 +02:00
parent 700356f93b
commit 59cce8237c
3 changed files with 10 additions and 2 deletions

View File

@ -1025,7 +1025,7 @@ class ModelAdmin(BaseModelAdmin):
orm_lookups = [construct_search(str(search_field)) orm_lookups = [construct_search(str(search_field))
for search_field in search_fields] for search_field in search_fields]
for bit in smart_split(search_term): for bit in smart_split(search_term):
if bit.startswith(('"', "'")): if bit.startswith(('"', "'")) and bit[0] == bit[-1]:
bit = unescape_string_literal(bit) bit = unescape_string_literal(bit)
or_queries = [models.Q(**{orm_lookup: bit}) or_queries = [models.Q(**{orm_lookup: bit})
for orm_lookup in orm_lookups] for orm_lookup in orm_lookups]

View File

@ -26,3 +26,7 @@ Bugfixes
* Fixed a bug in Django 3.2 where a system check would crash on a reverse * Fixed a bug in Django 3.2 where a system check would crash on a reverse
one-to-one relationships in ``CheckConstraint.check`` or one-to-one relationships in ``CheckConstraint.check`` or
``UniqueConstraint.condition`` (:ticket:`32635`). ``UniqueConstraint.condition`` (:ticket:`32635`).
* Fixed a regression in Django 3.2 that caused a crash of
:attr:`.ModelAdmin.search_fields` when searching against phrases with
unbalanced quotes (:ticket:`32649`).

View File

@ -3537,6 +3537,7 @@ class AdminSearchTest(TestCase):
cls.per2 = Person.objects.create(name='Grace Hopper', gender=1, alive=False) cls.per2 = Person.objects.create(name='Grace Hopper', gender=1, alive=False)
cls.per3 = Person.objects.create(name='Guido van Rossum', gender=1, alive=True) cls.per3 = Person.objects.create(name='Guido van Rossum', gender=1, alive=True)
Person.objects.create(name='John Doe', gender=1) Person.objects.create(name='John Doe', gender=1)
Person.objects.create(name='John O"Hara', gender=1)
Person.objects.create(name="John O'Hara", gender=1) Person.objects.create(name="John O'Hara", gender=1)
cls.t1 = Recommender.objects.create() cls.t1 = Recommender.objects.create()
@ -3612,7 +3613,7 @@ class AdminSearchTest(TestCase):
response = self.client.get(reverse('admin:admin_views_person_changelist') + '?q=Gui') response = self.client.get(reverse('admin:admin_views_person_changelist') + '?q=Gui')
self.assertContains( self.assertContains(
response, response,
"""<span class="small quiet">1 result (<a href="?">5 total</a>)</span>""", """<span class="small quiet">1 result (<a href="?">6 total</a>)</span>""",
html=True html=True
) )
@ -3643,7 +3644,10 @@ class AdminSearchTest(TestCase):
("John Doe John", 0), ("John Doe John", 0),
('"John Do"', 1), ('"John Do"', 1),
("'John Do'", 1), ("'John Do'", 1),
("'John O\'Hara'", 0),
("'John O\\'Hara'", 1), ("'John O\\'Hara'", 1),
('"John O\"Hara"', 0),
('"John O\\"Hara"', 1),
] ]
for search, hits in tests: for search, hits in tests:
with self.subTest(search=search): with self.subTest(search=search):