Using separate forms for adding and changing in Django's admin
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).