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