소스 검색

Fixed #7497 -- Allowed overriding the order of apps and models in admin.

adontz 3 년 전
부모
커밋
2bee0b4328
5개의 변경된 파일63개의 추가작업 그리고 10개의 파일을 삭제
  1. 8 10
      django/contrib/admin/sites.py
  2. 33 0
      docs/ref/contrib/admin/index.txt
  3. 3 0
      docs/releases/4.1.txt
  4. 8 0
      tests/admin_views/customadmin.py
  5. 11 0
      tests/admin_views/tests.py

+ 8 - 10
django/contrib/admin/sites.py

@@ -526,16 +526,14 @@ class AdminSite:
                     "models": [model_dict],
                 }
 
-        if label:
-            return app_dict.get(label)
         return app_dict
 
-    def get_app_list(self, request):
+    def get_app_list(self, request, app_label=None):
         """
         Return a sorted list of all the installed apps that have been
         registered in this site.
         """
-        app_dict = self._build_app_dict(request)
+        app_dict = self._build_app_dict(request, app_label)
 
         # Sort the apps alphabetically.
         app_list = sorted(app_dict.values(), key=lambda x: x["name"].lower())
@@ -568,16 +566,16 @@ class AdminSite:
         )
 
     def app_index(self, request, app_label, extra_context=None):
-        app_dict = self._build_app_dict(request, app_label)
-        if not app_dict:
+        app_list = self.get_app_list(request, app_label)
+
+        if not app_list:
             raise Http404("The requested admin page does not exist.")
-        # Sort the models alphabetically within each app.
-        app_dict["models"].sort(key=lambda x: x["name"])
+
         context = {
             **self.each_context(request),
-            "title": _("%(app)s administration") % {"app": app_dict["name"]},
+            "title": _("%(app)s administration") % {"app": app_list[0]["name"]},
             "subtitle": None,
-            "app_list": [app_dict],
+            "app_list": app_list,
             "app_label": app_label,
             **(extra_context or {}),
         }

+ 33 - 0
docs/ref/contrib/admin/index.txt

@@ -2896,6 +2896,39 @@ Templates can override or extend base admin templates as described in
 
         The ``model`` variable for each model was added.
 
+.. method:: AdminSite.get_app_list(request, app_label=None)
+
+    Returns a list of applications from the :doc:`application registry
+    </ref/applications/>` available for the current user. You can optionally
+    pass an ``app_label`` argument to get details for a single app. Each entry
+    in the list is a dictionary representing an application with the following
+    keys:
+
+    * ``app_label``: the application label
+    * ``app_url``: the URL of the application index in the admin
+    * ``has_module_perms``: a boolean indicating if displaying and accessing of
+      the module's index page is permitted for the current user
+    * ``models``: a list of the models available in the application
+    * ``name``: name of the application
+
+    Each model is a dictionary with the following keys:
+
+    * ``model``: the model class
+    * ``object_name``: class name of the model
+    * ``name``: plural name of the model
+    * ``perms``: a ``dict`` tracking ``add``, ``change``, ``delete``, and
+      ``view`` permissions
+    * ``admin_url``: admin changelist URL for the model
+    * ``add_url``: admin URL to add a new model instance
+
+    Lists of applications and models are sorted alphabetically by their names.
+    You can override this method to change the default order on the admin index
+    page.
+
+    .. versionchanged:: 4.1
+
+        The ``app_label`` argument was added.
+
 .. method:: AdminSite.has_permission(request)
 
     Returns ``True`` if the user for the given ``HttpRequest`` has permission

+ 3 - 0
docs/releases/4.1.txt

@@ -63,6 +63,9 @@ Minor features
 
 * Related widget wrappers now have a link to object's change form.
 
+* The :meth:`.AdminSite.get_app_list` method now allows changing the order of
+  apps and models on the admin index page.
+
 :mod:`django.contrib.admindocs`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

+ 8 - 0
tests/admin_views/customadmin.py

@@ -35,6 +35,14 @@ class Admin2(admin.AdminSite):
     def password_change(self, request, extra_context=None):
         return super().password_change(request, {"spam": "eggs"})
 
+    def get_app_list(self, request, app_label=None):
+        app_list = super().get_app_list(request, app_label=app_label)
+        # Reverse order of apps and models.
+        app_list = list(reversed(app_list))
+        for app in app_list:
+            app["models"].sort(key=lambda x: x["name"], reverse=True)
+        return app_list
+
 
 class UserLimitedAdmin(UserAdmin):
     # used for testing password change on a user not in queryset

+ 11 - 0
tests/admin_views/tests.py

@@ -1358,6 +1358,17 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
         models = [model["name"] for model in response.context["app_list"][0]["models"]]
         self.assertSequenceEqual(models, sorted(models))
 
+    def test_app_index_context_reordered(self):
+        self.client.force_login(self.superuser)
+        response = self.client.get(reverse("admin2:app_list", args=("admin_views",)))
+        self.assertContains(
+            response,
+            "<title>Admin_Views administration | Django site admin</title>",
+        )
+        # Models are in reverse order.
+        models = [model["name"] for model in response.context["app_list"][0]["models"]]
+        self.assertSequenceEqual(models, sorted(models, reverse=True))
+
     def test_change_view_subtitle_per_object(self):
         response = self.client.get(
             reverse("admin:admin_views_article_change", args=(self.a1.pk,)),