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):