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

This commit is contained in:
adontz 2022-03-05 20:09:42 +04:00 committed by Mariusz Felisiak
parent d44951b36e
commit 2bee0b4328
5 changed files with 63 additions and 10 deletions

View File

@ -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 {}),
}

View File

@ -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

View File

@ -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`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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

View File

@ -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,)),