From 9b1158a7e0784686bbe5118a88d4804b99fa4fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=20S=C3=B5mermaa?= <mrts@users.noreply.github.com> Date: Sat, 7 Aug 2021 19:28:30 +0300 Subject: [PATCH] Fixed #32993 -- Added AutocompleteJsonView.serialize_result() to allow customization. --- AUTHORS | 2 +- django/contrib/admin/views/autocomplete.py | 12 +++++++++-- tests/admin_views/test_autocomplete_view.py | 24 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 3e4aa1aa2c..ea10220756 100644 --- a/AUTHORS +++ b/AUTHORS @@ -610,7 +610,7 @@ answer newbie questions, and generally made Django that much better: Martin Mahner <https://www.mahner.org/> Martin Maney <http://www.chipy.org/Martin_Maney> Martin von Gagern <gagern@google.com> - Mart Sõmermaa <http://mrts.pri.ee/> + Mart Sõmermaa <https://github.com/mrts> Marty Alchin <gulopine@gamemusic.org> Masashi Shibata <m.shibata1020@gmail.com> masonsimon+django@gmail.com diff --git a/django/contrib/admin/views/autocomplete.py b/django/contrib/admin/views/autocomplete.py index 3903e4c98c..26aff083b6 100644 --- a/django/contrib/admin/views/autocomplete.py +++ b/django/contrib/admin/views/autocomplete.py @@ -11,7 +11,8 @@ class AutocompleteJsonView(BaseListView): def get(self, request, *args, **kwargs): """ - Return a JsonResponse with search results of the form: + Return a JsonResponse with search results as defined in + serialize_result(), by default: { results: [{id: "123" text: "foo"}], pagination: {more: true} @@ -26,12 +27,19 @@ class AutocompleteJsonView(BaseListView): context = self.get_context_data() return JsonResponse({ 'results': [ - {'id': str(getattr(obj, to_field_name)), 'text': str(obj)} + self.serialize_result(obj, to_field_name) for obj in context['object_list'] ], 'pagination': {'more': context['page_obj'].has_next()}, }) + def serialize_result(self, obj, to_field_name): + """ + Convert the provided model object to a dictionary that is added to the + results list. + """ + return {'id': str(getattr(obj, to_field_name)), 'text': str(obj)} + def get_paginator(self, *args, **kwargs): """Use the ModelAdmin's paginator.""" return self.model_admin.get_paginator(self.request, *args, **kwargs) diff --git a/tests/admin_views/test_autocomplete_view.py b/tests/admin_views/test_autocomplete_view.py index aa978f7a83..0685d0ac75 100644 --- a/tests/admin_views/test_autocomplete_view.py +++ b/tests/admin_views/test_autocomplete_view.py @@ -1,3 +1,4 @@ +import datetime import json from contextlib import contextmanager @@ -293,6 +294,29 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): 'pagination': {'more': False}, }) + def test_serialize_result(self): + class AutocompleteJsonSerializeResultView(AutocompleteJsonView): + def serialize_result(self, obj, to_field_name): + return { + **super().serialize_result(obj, to_field_name), + 'posted': str(obj.posted), + } + + Question.objects.create(question='Question 1', posted=datetime.date(2021, 8, 9)) + Question.objects.create(question='Question 2', posted=datetime.date(2021, 8, 7)) + request = self.factory.get(self.url, {'term': 'question', **self.opts}) + request.user = self.superuser + response = AutocompleteJsonSerializeResultView.as_view(**self.as_view_args)(request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content.decode('utf-8')) + self.assertEqual(data, { + 'results': [ + {'id': str(q.pk), 'text': q.question, 'posted': str(q.posted)} + for q in Question.objects.order_by('-posted') + ], + 'pagination': {'more': False}, + }) + @override_settings(ROOT_URLCONF='admin_views.urls') class SeleniumTests(AdminSeleniumTestCase):