Autoregister Django ModelAdmins
Tags: django, python, tutorial
Published: 2022-06-07 10:25:40


Some time ago I discovered that Django has the ability to auto-register `ModelAdmins`. Since this is not common knowledge and carries a number of benefits, I decided to write an article about it to bring it to the attention of the Django community.

First, let's go over the basics of how to normally register `ModelAdmin`.

## Standard `ModelAdmin` registration

To register `ModelAdmin`, we first create a model

{% embed https://gist.github.com/danilovmy/3a74bf5c7d02c32ffab0e8305594f610.js %}

Next you need to create a `ModelAdmin` and register it with the model on the `SiteAdmin`.

{% embed https://gist.github.com/danilovmy/3862278887ee6cedfca9c0c97698c50e.js %}

Now let's run our dev server and see if it worked.

![admin panel registered models](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vejd0dodot6i10vi8zl8.PNG)

But what are these? Some additional `ModelAdmins` are registered, but we've never defined them. This means Django is auto-registering these standard `ModelAdmins` somewhere.

## Django `ModelAdmins` integrated auto-register.

After some digging in `django.contrib.admin.apps`, I found that these `ModelAdmins` are registered in the `ready` method of the `AdminConfig` class.

```
class AdminConfig(SimpleAdminConfig):
    """The default AppConfig for admin which does autodiscovery."""

    default = True

    def ready(self):
        super().ready()
        self.module.autodiscover()
```

We can use this fact to our advantage if we wrap this method not only for auto-registering the standard Django models, but also for our own.

We can do this as follows:

{% embed https://gist.github.com/danilovmy/77d0d742a8f2c768eb29f40f3707ec3b.js %}

We go through all `AppConfigs` in our project and get the admin module from `AppConfigs`. Of course, this is the case if the admin module exists.
We then go through all models from this `AppConfig`.
There we check if the model has already been registered with `SiteAdmin`.

If not, we search for `ModelAdmin` class with name '*model_name*ModelAdmin' in the admin module. If no such class is defined, we use `None`.

Finally, we register the model using the found `ModelAdmin`on `SiteAdmin`.

If `ModelAdmin` is not defined, the `register` method registers the model to `ModelAdmin` class by default.

But why should you do it this anyway?

## Benefits

### 1. Shorter Code

With this approach to registering `ModelAdmins` you can multiple  lines of code in one 10-line solution.

You can say goodbye to the empty `ModelAdmin` classes just to register the model, if you done it before. 
No more `@admin.register(model)` wrappers on any `ModelAdmin`.
Most importantly, no more long import lists for your models in the module admin.

Depending on how many models you have and how many `ModelAdmins` need to be registered you can save a lot of lines of code.


### 2. Easier development

Continuing with the idea of the previous point, you no longer need to worry about registering `ModelAdmin` during development because everything happens automatically when the server starts up.


### 3. Circular Imports

With the current system with huge import lists in the admin module, it is not that difficult to get circular imports and find a workaround. With this solution, these import lists are gone and you no longer have to worry about models and circular import.

## Variations

Sometimes you don't want register on the current `SiteAdmin` all of your models, so what do you do then?

Of course you can modify the solution above as you wish, but here I want to give you some ideas for solving the most common problems.

### Register specific models only

If we want to register only the required models with `ModelAdmins`, we can define only the required `ModelAdmins` in the admin module and do the following:

{% embed https://gist.github.com/danilovmy/2bcc14b9af8fbc3ced1a4c14b5c5f664.js %}

In this solution you need to add in the admin module `**ModelName**ModelAdmin` class for each required model.

Alternatively you can add a flag to the model if it should be auto-registered.

{% embed https://gist.github.com/danilovmy/60b0f8b80aab298189e794eb44200e2d.js %}

### Remove standard registered models

Perhaps you don't need the standard Django models registered in your project. You can remove them with one simple line added to the ready method.

{% embed https://gist.github.com/danilovmy/ed961527bc023d23916aae7ee30d3cb8.js %}

These are just some of the options for using Django autoregister. I'm sure you can think of other clever ways to use it, and I hope this article was useful.

I thank Martin Achenrainer, who is an apprentice at my firm, for translating and assisting with the English article. The idea was first [presented](https://www.youtube.com/watch?v=5tJdO0bkb3A) in September 2021 at PyCon RU

**Some words from Martin Achenrainer.**
> I would like to thank Maxim Danilov and his company wP soft for the opportunity to learn and improve my programming skills in the workplace.