Skip to content
Using separate forms for adding and changing in Django's admin

Using separate forms for adding and changing in Django's admin

January 4, 2009

The Django documentation describes how to override the form class used by the admin site when adding or editing your objects. It is easy, you just specify a form attribute on your ModelAdmin sub-class, and point it at your custom Form or ModelForm class.

But there is no documented method to specify one form class for creating an object and a different form class for editing an object.

My solution is to override the get_form method on your ModelAdmin sub-class. When adding an object, ModelAdmin will use the add_view method, whereas when changing an existing object ModelAdmin will use the change_view method. You could override the add_view method and specify a different form class there, but you would need to handle the entire business of object creation, including checking the client has permission, validating the form instance and populating the template context. Django’s auth application takes that approach for adding a new user, providing a simple username / password form in place of the full-blown object form.

A simpler method is to override get_form. When changing an object, get_form is called with the optional argument obj set to the object instance. When adding an object the obj argument is None. This makes it easy to determine when to return a different form for adding versus changing.

Here is an example of how to sub-class ModelAdmin and override the get_form method to return a different form depending on whether the client is adding a new object or changing an existing object.

# admin.py
from django.contrib import admin
from forms import MyAddForm
from models import MyModel


class MyModelAdmin(admin.ModelAdmin):
    """A ModelAdmin that uses a different form class when adding an object."""
    def get_form(self, request, obj=None, **kwargs):
        if obj is None:
            return MyAddForm
        else:
            return super(MyModelAdmin, self).get_form(request, obj, **kwargs)


admin.site.register(MyModel, MyModelAdmin)

Note a certain amount of hand-waving in the example where I’ve assumed that the appropriate models and forms are defined elsewhere. The custom form class will need to be a sub-class of ModelForm (or at least implement a suitable save method).

Last updated on