Search code examples
pythondjangodjango-admindjango-admin-filters

How can I automatically create list_filters for all my models in a django admin page?


I have a Django site, using admin to manage the models. Currently, I am using

from django.db.models.base import ModelBase

for name, var in databuild_models.__dict__.items():
    if type(var) is ModelBase:
        admin.site.register(var)

To register all the models in the module with the admin module. However, I want to automatically add list_filters for every attribute on each model. I've read https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ where they use the form:

class MymodelAdmin(admin.ModelAdmin):
    list_filter = ['model_name_attribute']

and then

admin.site.register(models.MyModel, MyModelAdmin)

Is there a way to similarly loop through each attribute in a model, and add it to a filter list?

For example:

filter_list_fields = []
for attr in MyModel:
    filter_list_fields.append(str(attr))
list_filter = filter_list_fields

and then register them as a general class?


Solution

  • Firstly, you can use the applications api to get a list of models in your app, rather than inspecting the module's __dict__

    In Django 1.8+, you can get a list of field names for a model using Model._meta.get_fields method. I've excluded the automatically generated id field, and you might find you want to make further improvements.

    In python, you can create a class dynamically using type. You need the name of the new class (not important here), the base classes that it inherits from (in this case Admin.ModelAdmin, and a dictionary of attributes (in this case, there is only one attribute, list_filter).

    Finally, register the model with the custom model admin we have created.

    Putting it together, your admin.py should look something like this:

    from django.contrib import admin
    from django.apps import apps
    
    app_config  = apps.get_app_config('myapp')
    models = app_config.get_models()
    
    for Model in models:
        fieldnames = [f.name for f in Model._meta.get_fields() if f.name != 'id']
        ModelAdmin = type('ModelAdmin', (admin.ModelAdmin,), {'list_filter': fieldnames})
        admin.site.register(Model, ModelAdmin)