Defining a custom app_list in django admin index page

前端 未结 5 576
面向向阳花
面向向阳花 2020-12-28 08:36

I\'d like to define a custom application list to use in django\'s admin index page because I want the apps displayed in a specific order, rather than the default alphabetica

5条回答
  •  Happy的楠姐
    2020-12-28 09:01

    If you don't mind to use a subclass of django.contrib.admin.site.AdminSite(), as expected in cases when you need to customize your admin site, I think it's a feasible idea rewriting "index" and "app_index" methods in the derived class. You can do custom ordering using two dictionaries that store the app declararion order in settings.py and the registration order of models. Then rewrite the code of the original AdminSite().index() and app_index(), adding a custom order fields ('order') in app_list and order by this field despite 'name'. This is the code, excluding app_index(), that is similar to index() function:

    class MyAdminSite(AdminSite):
    
        def __init__(self, name='admin', app_name='admin'):
            super(MyAdminSite, self).__init__(name, app_name)
    
            # Model's registration ordering. It's not necessary to
            # categorize by app.
            self._registry_ord = {}
    
            # App ordering determined by declaration
            self._app_ord = { 'auth' : 0 }
            app_position = 1
            for app in settings.INSTALLED_APPS:
                self._app_ord[app] = app_position
                app_position += 1
    
        def register(self, model_or_iterable, admin_class=None, **options):
            super(MyAdminSite, self).register(model_or_iterable, admin_class, **options)
    
            if isinstance(model_or_iterable, ModelBase):
                model_or_iterable = [model_or_iterable]
            for model in model_or_iterable:
                if model in self._registry:
                    if self._registry_ord:
                        self._registry_ord[model._meta.object_name] = max(self._registry_ord.values()) + 1 
                    else:
                        self._registry_ord[model._meta.object_name] = 1
    
        @never_cache
        def index(self, request, extra_context=None):
            """
            Displays the main admin index page, which lists all of the installed
            apps that have been registered in this site.
            """
            app_dict = {}
            user = request.user
            for model, model_admin in self._registry.items():
                app_label = model._meta.app_label
                has_module_perms = user.has_module_perms(app_label)
    
                if has_module_perms:
                    perms = model_admin.get_model_perms(request)
    
                    # Check whether user has any perm for this module.
                    # If so, add the module to the model_list.
                    if True in perms.values():
                        info = (app_label, model._meta.module_name)
                        model_dict = {
                            'name': capfirst(model._meta.verbose_name_plural),
                            'perms': perms,
                            'order': self._registry_ord[model._meta.object_name]
                        }
                        if perms.get('change', False):
                            try:
                                model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
                            except NoReverseMatch:
                                pass
                        if perms.get('add', False):
                            try:
                                model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=self.name)
                            except NoReverseMatch:
                                pass
                        if app_label in app_dict:
                            app_dict[app_label]['models'].append(model_dict)
                        else:
                            app_dict[app_label] = {
                                'name': app_label.title(),
                                'app_url': reverse('admin:app_list', kwargs={'app_label': app_label}, current_app=self.name),
                                'has_module_perms': has_module_perms,
                                'models': [model_dict],
                                'order': self._app_ord[app_label],
                            }
    
            # Sort the apps alphabetically.
            app_list = app_dict.values()
            app_list.sort(key=lambda x: x['order'])
    
            # Sort the models alphabetically within each app.
            for app in app_list:
                app['models'].sort(key=lambda x: x['order'])
    
            context = {
                'title': _('Site administration'),
                'app_list': app_list,
            }
            context.update(extra_context or {})
            return TemplateResponse(request, [
                self.index_template or 'admin/index.html',
            ], context, current_app=self.name)
    

    If you use custom AdminSite and you want to include Auth models you probably need this, somewhere in your code (I made it in a specific app to extend user information :

    from django.contrib.auth.models import User, Group
    from myproject import admin
    
    admin.site.register(User)
    admin.site.register(Group)
    

提交回复
热议问题