Learn how to write your own framework in Python!

You'll learn how to develop your own Python web framework to see how all the magic works beneath the scenes in Flask, Django, and the other Python-based web frameworks.

Jahongir Rahmonov

I'm a Software Engineer at Delivery Hero. Avid reader. WIUT graduate. Blogger and an amateur speaker.

I write about Python, Django, Kubernetes and sometimes something non-technical.

Welcome to my corner

Sun 18 October 2015

Customize django admin templates

Quite often, we need to customize the django admin template: to add additional functionality or just change its look and feel.

Recently, I had the task of adding an ajax request on admin page load(specifically, change_form.html) and adding two buttons, one of which would bring a modal up and the other would delete the selected items which, in their turn, were brought by that ajax request.

Here is what I did and went through:


First, I created a change_form.html file in /templates/admin/ folder. As I wanted this file to extend, not replace, the default change_form.html, I wrote this at the beginning of the file:

{% extends 'admin/change_form.html' %}

This, naturally, led to maximum recursin depth exceeded error as it was trying to extend itself.

Then, I read somewhere that I could put this file in /templates/admin/app_name folder, so that it will change the templates of only this app. Voila! Recursion problem solved.

Then, I added all those buttons and modals I wanted to(more on this later). Everything was working fine until I found out that the buttons I added appear on the admin pages of all the models in the app. But I wanted them to appear only on the admin pages of, let's say, product model.

Turned out, the same works here. I just needed to put the file inside /templates/admin/app_name/model_name. In my case, it the file was /templates/admin/enterprise/product.

Styles, Scripts and Buttons

Where do I put them? Taking a look at admin/base.html did the trick. It has special blocks for extra styles and scripts. So I put my css and javascript files in the following way:

{% block extrastyle %}
    {{ block.super }}

    <link rel="stylesheet" href="{% static 'css/enterprise/main.css'%}">
{% endblock %}

{% block extrahead %}
    {{ block.super }}

    <script type="text/javascript" src="{% static 'js/enterprise/modal.js'%}"></script>
{% endblock %}

As for buttons, I thought a good place would be above the default buttons. So, I thought out the block of those buttons and put mine right above them:

{% block submit_buttons_bottom %}
    <div class="submit-row">
        <button class="btn btn-danger">Custom Button</button>

    {{ block.super }}
{% endblock %}

As I was using django-admin-bootstrapped, submit-row gave the div nice and natural look.


In the ajax request, I had to send the id of the product being changed. So I thought I could get it with {{ product.id }} but I was wrong. Then, I learned that I could get it like so:

{{ original.id }}

So, the model instance being dealt with can be accessed with the word original. How original, isn't it?

Wrap up

Either I am bad at reading the documentation or it could be improved a little further. Probably first option.

I hope it will help somebody save some time in the future.

Fight on!


If you liked what you read, subscribe below. Once in a while, I will send you a list of my new posts.