Recently I've received an interesting request from a client about one of our Django projects.
He asked if it would be possible to show an inline component above other fields in the Django admin panel.
At the beginning I thought, that there shouldn't be any issue with that.
Though there was no easy solution other then installing another battery to the project. My gut feeling told me, there were another way around that problem.
The first solution I found was from 2017. It had too much code for such a simple task.
Our executive lead programmer, Maxim Danilov found quite a short solution. He published his work online in russian about a month ago.
I´d like to share these ideas with englisch speaking Django community in order to help others simplify their code. It might come handy for such a "simple" at first glance issues.
Long story short, let's dive into the code:
Imagine you are building an E-commerce project. You have a
ProductModelwhich have O2M relation to
You also need
ModelAdmins for given models.
Now let's create a simple inline to put into our
I suppose, you are familiar with the added field concept in
ModelAdminForm. You can create a method in the
ModelAdmin to display the response of the method in the form as a readonly field.
Keep in mind, that the rendering sequence of the
ModelAdmin will create the
InlineModels first, then render
AdminForm and after that render the
We can use that to rearrange the order of Inlines and fields.
We use the
render_change_form to get the objects
We use those objects in the
image_inline method to take one
inline_formset from the list of
inline_admin_formsets that have not been processed yet, and render
change_form rendering the remaining
inline_admin_formsets will be rendered, in case if the
ModelAdmin still has some.
Now we can use the method
image_inline to determine the position of our
With the code-snippet above the inline element will be placed above all other fields.
Of course Django admin adds a lable infront of the Inline with the name of the method, but that can be easily removed by some simple CSS in
Media attribute of
This solution has one fatal error! Every Django ModelAdmin is singelton, that is why we can not use ModelAdmin.self as a container in
It is possible to change the ModelAdmins singleton´s behavior with a Mixin, staying inline with the concept of Djangos GCBV. We will take a closer look at it in my next article.
It simply means, that we can't use the instance of the
ModelAdmin as a container to save our
The solution is to save those objects in the
obj is not always given in
render_change_form (i.e. add new object). That is why we have to get it from the
ModelForm, which is wrapped into the
Now we can set our request and response as attributes of the
ModelForm instance and use those in
Summing up the above: you don't have to install another battery to your project to solve a simple problem. Sometimes you need to dig deep enough into the framework that you use, and find a simple, short and quick solution.
I´d like to thank Martin Achenrainer the intern of wPsoft for contributing to this article and translating it.