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

The [Django documentation][1] describes [how to override the form class used by
the admin site][2] 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][3] 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).

[1]: http://docs.djangoproject.com/
[2]: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#form
[3]: http://code.djangoproject.com/browser/django/tags/releases/1.0.2/django/contrib/auth/admin.py

3 thoughts on “Using separate forms for adding and changing in Django’s admin

  1. Jason

    This is so confusing still because you have not indicated how to return myEditForm. I appreciate your post, could you make this clear?

  2. louity

    This solution is not correct, beacause then the form might not be correctly displayed in Admin.

    The correct solution is :

    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:
    self.form = MyAddForm
    return super(MyModelAdmin, self).get_form(request, obj, **kwargs)

  3. louity

    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)

Leave a Reply

Your email address will not be published. Required fields are marked *