Wednesday, 15 October 2014

Overriding forms in Django admin.

First up, find out where your python packages are stored. This will differ from your system packages if you are in a virtualenv.

echo `which python`

You will get a path like this

/some/path/bin/python

Navigate up a couple of directories and find the django package. Then browse to the following directory. Here you will find all the original templates for django admin.

/some/path/lib/python2.7/site-packages/django/contrib/admin/templates/admin/

My use case required overriding change forms for particular models of some applications.

This is the form that you get once an object of a particular model is saved and you need to change some values / fields in that model.

Copy the change_form.html from the directory and paste it in your projects templates folder. The path would depend on which model you are overriding. Suppose you have model Foo in application ABC.

Copy change_form.html to

templates/admin/ABC/foo/change_form.html

(creating directories where needed). This is your projects' templates folder.

Application name reserves the casing but the model name should be converted to lowercase.

Inside this template you can use {{ original }} along with {{ block.super}} to access the particular object of the model whose form you have overridden. A typical override would look like this, removing the unnecessary stuff.


{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}

{% load static %}

{% block extrahead %}{{ block.super }}
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
	<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
	<script src="{% static "js/custom.js" %}"></script>
{% endblock %}


{% block after_field_sets %}{{ block.super }}
    <!-- override template here -->
{% endblock %}


You can also override inlines. Suppose you are using ModelAdmin and need to override an inline.
You must add an additional attribute named template to the inline, and giving it the path of the form you have overridden.


We maintain the same directory path convention as found in the site-packages/django/.. directory. But this is not necessary, stacked.html can reside anywhere under templates. Copy it under your templates from the same directory that you copied change_form.html from.


class FooInline(admin.StackedInline):
	model = Foo
	fields = (('a'),('b'),('c'),)
	extra = 0
        template = 'admin/ABC/bar/edit_inline/stacked.html'

class BarAdmin(admin.ModelAdmin):
	list_display = ['b', 'a', 'r']
	inlines = [FooInline]

admin.site.register(Bar, BarAdmin)

admin.site.register(Foo)


Extra headers can be added under the extrahead block.


{% block extrahead %}
    <!-- extra css/js resources defined here -->
{% endblock %}


Custom JavaScript can be linked in the extrahead block or you can have it on the page at the end of the template. Note that if you intend on adding some forms, and have input or button with type="submit", it conflicts with the model's form (you should be able to stop event propagation by handling it, I suppose, this remains to be tried).

If you need to process any input separately, have a button tag with an event listener on it.

No comments:

Post a Comment