Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[1.2.X] Fixed #14835 -- Corrected a lack of indentation in the reST m…

…arkup for docs/ref/contrib/admin/index.txt and reflowed the text accordingly.

Thanks to cogat for the report.

Backport of [14830] from trunk - approximate, because other changes have
made it very hard to do exactly.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15620 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 25c217bc170d275a2db65fd9c9faa064797d4b2f 1 parent 58c4aca
Luke Plant spookylukey authored
Showing with 623 additions and 601 deletions.
  1. +623 −601 docs/ref/contrib/admin/index.txt
1,224 docs/ref/contrib/admin/index.txt
View
@@ -61,30 +61,31 @@ Other topics
.. class:: ModelAdmin
-The ``ModelAdmin`` class is the representation of a model in the admin
-interface. These are stored in a file named ``admin.py`` in your application.
-Let's take a look at a very simple example of the ``ModelAdmin``::
+ The ``ModelAdmin`` class is the representation of a model in the admin
+ interface. These are stored in a file named ``admin.py`` in your
+ application. Let's take a look at a very simple example of
+ the ``ModelAdmin``::
- from django.contrib import admin
- from myproject.myapp.models import Author
+ from django.contrib import admin
+ from myproject.myapp.models import Author
- class AuthorAdmin(admin.ModelAdmin):
- pass
- admin.site.register(Author, AuthorAdmin)
+ class AuthorAdmin(admin.ModelAdmin):
+ pass
+ admin.site.register(Author, AuthorAdmin)
-.. admonition:: Do you need a ``ModelAdmin`` object at all?
+ .. admonition:: Do you need a ``ModelAdmin`` object at all?
- In the preceding example, the ``ModelAdmin`` class doesn't define any
- custom values (yet). As a result, the default admin interface will be
- provided. If you are happy with the default admin interface, you don't
- need to define a ``ModelAdmin`` object at all -- you can register the
- model class without providing a ``ModelAdmin`` description. The
- preceding example could be simplified to::
+ In the preceding example, the ``ModelAdmin`` class doesn't define any
+ custom values (yet). As a result, the default admin interface will be
+ provided. If you are happy with the default admin interface, you don't
+ need to define a ``ModelAdmin`` object at all -- you can register the
+ model class without providing a ``ModelAdmin`` description. The
+ preceding example could be simplified to::
- from django.contrib import admin
- from myproject.myapp.models import Author
+ from django.contrib import admin
+ from myproject.myapp.models import Author
- admin.site.register(Author)
+ admin.site.register(Author)
``ModelAdmin`` Options
----------------------
@@ -98,619 +99,629 @@ subclass::
.. attribute:: ModelAdmin.date_hierarchy
-Set ``date_hierarchy`` to the name of a ``DateField`` or ``DateTimeField`` in
-your model, and the change list page will include a date-based drilldown
-navigation by that field.
+ Set ``date_hierarchy`` to the name of a ``DateField`` or ``DateTimeField``
+ in your model, and the change list page will include a date-based drilldown
+ navigation by that field.
-Example::
+ Example::
- date_hierarchy = 'pub_date'
+ date_hierarchy = 'pub_date'
.. attribute:: ModelAdmin.form
-By default a ``ModelForm`` is dynamically created for your model. It is used
-to create the form presented on both the add/change pages. You can easily
-provide your own ``ModelForm`` to override any default form behavior on the
-add/change pages.
+ By default a ``ModelForm`` is dynamically created for your model. It is
+ used to create the form presented on both the add/change pages. You can
+ easily provide your own ``ModelForm`` to override any default form behavior
+ on the add/change pages.
-For an example see the section `Adding custom validation to the admin`_.
+ For an example see the section `Adding custom validation to the admin`_.
.. attribute:: ModelAdmin.fieldsets
-Set ``fieldsets`` to control the layout of admin "add" and "change" pages.
-
-``fieldsets`` is a list of two-tuples, in which each two-tuple represents a
-``<fieldset>`` on the admin form page. (A ``<fieldset>`` is a "section" of the
-form.)
-
-The two-tuples are in the format ``(name, field_options)``, where ``name`` is a
-string representing the title of the fieldset and ``field_options`` is a
-dictionary of information about the fieldset, including a list of fields to be
-displayed in it.
-
-A full example, taken from the ``django.contrib.flatpages.FlatPage`` model::
-
- class FlatPageAdmin(admin.ModelAdmin):
- fieldsets = (
- (None, {
- 'fields': ('url', 'title', 'content', 'sites')
- }),
- ('Advanced options', {
- 'classes': ('collapse',),
- 'fields': ('enable_comments', 'registration_required', 'template_name')
- }),
- )
+ Set ``fieldsets`` to control the layout of admin "add" and "change" pages.
+
+ ``fieldsets`` is a list of two-tuples, in which each two-tuple represents a
+ ``<fieldset>`` on the admin form page. (A ``<fieldset>`` is a "section" of
+ the form.)
+
+ The two-tuples are in the format ``(name, field_options)``, where ``name``
+ is a string representing the title of the fieldset and ``field_options`` is
+ a dictionary of information about the fieldset, including a list of fields
+ to be displayed in it.
+
+ A full example, taken from the ``django.contrib.flatpages.FlatPage``
+ model::
+
+ class FlatPageAdmin(admin.ModelAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': ('url', 'title', 'content', 'sites')
+ }),
+ ('Advanced options', {
+ 'classes': ('collapse',),
+ 'fields': ('enable_comments', 'registration_required', 'template_name')
+ }),
+ )
-This results in an admin page that looks like:
+ This results in an admin page that looks like:
- .. image:: _images/flatfiles_admin.png
+ .. image:: _images/flatfiles_admin.png
-If ``fieldsets`` isn't given, Django will default to displaying each field
-that isn't an ``AutoField`` and has ``editable=True``, in a single fieldset,
-in the same order as the fields are defined in the model.
+ If ``fieldsets`` isn't given, Django will default to displaying each field
+ that isn't an ``AutoField`` and has ``editable=True``, in a single
+ fieldset, in the same order as the fields are defined in the model.
-The ``field_options`` dictionary can have the following keys:
+ The ``field_options`` dictionary can have the following keys:
- * ``fields``
- A tuple of field names to display in this fieldset. This key is
- required.
+ * ``fields``
+ A tuple of field names to display in this fieldset. This key is
+ required.
- Example::
+ Example::
- {
- 'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
- }
+ {
+ 'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
+ }
- To display multiple fields on the same line, wrap those fields in
- their own tuple. In this example, the ``first_name`` and ``last_name``
- fields will display on the same line::
+ To display multiple fields on the same line, wrap those fields in
+ their own tuple. In this example, the ``first_name`` and
+ ``last_name`` fields will display on the same line::
- {
- 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
- }
+ {
+ 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
+ }
- .. versionadded:: 1.2
+ .. versionadded:: 1.2
- ``fields`` can contain values defined in
- :attr:`~ModelAdmin.readonly_fields` to be displayed as read-only.
+ ``fields`` can contain values defined in
+ :attr:`~ModelAdmin.readonly_fields` to be displayed as read-only.
- * ``classes``
- A list containing extra CSS classes to apply to the fieldset.
+ * ``classes``
+ A list containing extra CSS classes to apply to the fieldset.
- Example::
+ Example::
- {
- 'classes': ['wide', 'extrapretty'],
- }
+ {
+ 'classes': ['wide', 'extrapretty'],
+ }
- Two useful classes defined by the default admin site stylesheet are
- ``collapse`` and ``wide``. Fieldsets with the ``collapse`` style will
- be initially collapsed in the admin and replaced with a small
- "click to expand" link. Fieldsets with the ``wide`` style will be
- given extra horizontal space.
+ Two useful classes defined by the default admin site stylesheet are
+ ``collapse`` and ``wide``. Fieldsets with the ``collapse`` style
+ will be initially collapsed in the admin and replaced with a small
+ "click to expand" link. Fieldsets with the ``wide`` style will be
+ given extra horizontal space.
- * ``description``
- A string of optional extra text to be displayed at the top of each
- fieldset, under the heading of the fieldset.
+ * ``description``
+ A string of optional extra text to be displayed at the top of each
+ fieldset, under the heading of the fieldset.
- Note that this value is *not* HTML-escaped when it's displayed in
- the admin interface. This lets you include HTML if you so desire.
- Alternatively you can use plain text and
- ``django.utils.html.escape()`` to escape any HTML special
- characters.
+ Note that this value is *not* HTML-escaped when it's displayed in
+ the admin interface. This lets you include HTML if you so desire.
+ Alternatively you can use plain text and
+ ``django.utils.html.escape()`` to escape any HTML special
+ characters.
.. attribute:: ModelAdmin.fields
-Use this option as an alternative to ``fieldsets`` if the layout does not
-matter and if you want to only show a subset of the available fields in the
-form. For example, you could define a simpler version of the admin form for
-the ``django.contrib.flatpages.FlatPage`` model as follows::
+ Use this option as an alternative to ``fieldsets`` if the layout does not
+ matter and if you want to only show a subset of the available fields in the
+ form. For example, you could define a simpler version of the admin form for
+ the ``django.contrib.flatpages.FlatPage`` model as follows::
- class FlatPageAdmin(admin.ModelAdmin):
- fields = ('url', 'title', 'content')
+ class FlatPageAdmin(admin.ModelAdmin):
+ fields = ('url', 'title', 'content')
-In the above example, only the fields 'url', 'title' and 'content' will be
-displayed, sequentially, in the form.
+ In the above example, only the fields 'url', 'title' and 'content' will be
+ displayed, sequentially, in the form.
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-``fields`` can contain values defined in :attr:`ModelAdmin.readonly_fields`
-to be displayed as read-only.
+ ``fields`` can contain values defined in :attr:`ModelAdmin.readonly_fields`
+ to be displayed as read-only.
-.. admonition:: Note
+ .. admonition:: Note
- This ``fields`` option should not be confused with the ``fields``
- dictionary key that is within the ``fieldsets`` option, as described in
- the previous section.
+ This ``fields`` option should not be confused with the ``fields``
+ dictionary key that is within the ``fieldsets`` option, as described in
+ the previous section.
-.. attribute:: ModelAdmin.exclude
+ .. attribute:: ModelAdmin.exclude
-This attribute, if given, should be a list of field names to exclude from the
-form.
+ This attribute, if given, should be a list of field names to exclude from
+ the form.
-For example, let's consider the following model::
+ For example, let's consider the following model::
- class Author(models.Model):
- name = models.CharField(max_length=100)
- title = models.CharField(max_length=3)
- birth_date = models.DateField(blank=True, null=True)
+ class Author(models.Model):
+ name = models.CharField(max_length=100)
+ title = models.CharField(max_length=3)
+ birth_date = models.DateField(blank=True, null=True)
-If you want a form for the ``Author`` model that includes only the ``name``
-and ``title`` fields, you would specify ``fields`` or ``exclude`` like this::
+ If you want a form for the ``Author`` model that includes only the ``name``
+ and ``title`` fields, you would specify ``fields`` or ``exclude`` like
+ this::
- class AuthorAdmin(admin.ModelAdmin):
- fields = ('name', 'title')
+ class AuthorAdmin(admin.ModelAdmin):
+ fields = ('name', 'title')
- class AuthorAdmin(admin.ModelAdmin):
- exclude = ('birth_date',)
+ class AuthorAdmin(admin.ModelAdmin):
+ exclude = ('birth_date',)
-Since the Author model only has three fields, ``name``, ``title``, and
-``birth_date``, the forms resulting from the above declarations will contain
-exactly the same fields.
+ Since the Author model only has three fields, ``name``, ``title``, and
+ ``birth_date``, the forms resulting from the above declarations will
+ contain exactly the same fields.
-.. attribute:: ModelAdmin.filter_horizontal
+ .. attribute:: ModelAdmin.filter_horizontal
-Use a nifty unobtrusive JavaScript "filter" interface instead of the
-usability-challenged ``<select multiple>`` in the admin form. The value is a
-list of fields that should be displayed as a horizontal filter interface. See
-``filter_vertical`` to use a vertical interface.
+ Use a nifty unobtrusive JavaScript "filter" interface instead of the
+ usability-challenged ``<select multiple>`` in the admin form. The value is
+ a list of fields that should be displayed as a horizontal filter interface.
+ See ``filter_vertical`` to use a vertical interface.
-.. attribute:: ModelAdmin.filter_vertical
+ .. attribute:: ModelAdmin.filter_vertical
-Same as ``filter_horizontal``, but is a vertical display of the filter
-interface.
+ Same as ``filter_horizontal``, but is a vertical display of the filter
+ interface.
.. attribute:: ModelAdmin.list_display
-Set ``list_display`` to control which fields are displayed on the change list
-page of the admin.
+ Set ``list_display`` to control which fields are displayed on the change
+ list page of the admin.
-Example::
+ Example::
- list_display = ('first_name', 'last_name')
+ list_display = ('first_name', 'last_name')
-If you don't set ``list_display``, the admin site will display a single column
-that displays the ``__unicode__()`` representation of each object.
+ If you don't set ``list_display``, the admin site will display a single
+ column that displays the ``__unicode__()`` representation of each object.
-You have four possible values that can be used in ``list_display``:
+ You have four possible values that can be used in ``list_display``:
- * A field of the model. For example::
+ * A field of the model. For example::
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('first_name', 'last_name')
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'last_name')
- * A callable that accepts one parameter for the model instance. For
- example::
+ * A callable that accepts one parameter for the model instance. For
+ example::
- def upper_case_name(obj):
- return ("%s %s" % (obj.first_name, obj.last_name)).upper()
- upper_case_name.short_description = 'Name'
+ def upper_case_name(obj):
+ return ("%s %s" % (obj.first_name, obj.last_name)).upper()
+ upper_case_name.short_description = 'Name'
- class PersonAdmin(admin.ModelAdmin):
- list_display = (upper_case_name,)
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = (upper_case_name,)
- * A string representing an attribute on the ``ModelAdmin``. This behaves
- same as the callable. For example::
+ * A string representing an attribute on the ``ModelAdmin``. This
+ behaves same as the callable. For example::
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('upper_case_name',)
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('upper_case_name',)
- def upper_case_name(self, obj):
- return ("%s %s" % (obj.first_name, obj.last_name)).upper()
- upper_case_name.short_description = 'Name'
+ def upper_case_name(self, obj):
+ return ("%s %s" % (obj.first_name, obj.last_name)).upper()
+ upper_case_name.short_description = 'Name'
- * A string representing an attribute on the model. This behaves almost
- the same as the callable, but ``self`` in this context is the model
- instance. Here's a full model example::
+ * A string representing an attribute on the model. This behaves almost
+ the same as the callable, but ``self`` in this context is the model
+ instance. Here's a full model example::
- class Person(models.Model):
- name = models.CharField(max_length=50)
- birthday = models.DateField()
+ class Person(models.Model):
+ name = models.CharField(max_length=50)
+ birthday = models.DateField()
- def decade_born_in(self):
- return self.birthday.strftime('%Y')[:3] + "0's"
- decade_born_in.short_description = 'Birth decade'
+ def decade_born_in(self):
+ return self.birthday.strftime('%Y')[:3] + "0's"
+ decade_born_in.short_description = 'Birth decade'
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('name', 'decade_born_in')
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('name', 'decade_born_in')
-A few special cases to note about ``list_display``:
+ A few special cases to note about ``list_display``:
- * If the field is a ``ForeignKey``, Django will display the
- ``__unicode__()`` of the related object.
+ * If the field is a ``ForeignKey``, Django will display the
+ ``__unicode__()`` of the related object.
- * ``ManyToManyField`` fields aren't supported, because that would entail
- executing a separate SQL statement for each row in the table. If you
- want to do this nonetheless, give your model a custom method, and add
- that method's name to ``list_display``. (See below for more on custom
- methods in ``list_display``.)
+ * ``ManyToManyField`` fields aren't supported, because that would
+ entail executing a separate SQL statement for each row in the table.
+ If you want to do this nonetheless, give your model a custom method,
+ and add that method's name to ``list_display``. (See below for more
+ on custom methods in ``list_display``.)
- * If the field is a ``BooleanField`` or ``NullBooleanField``, Django will
- display a pretty "on" or "off" icon instead of ``True`` or ``False``.
+ * If the field is a ``BooleanField`` or ``NullBooleanField``, Django
+ will display a pretty "on" or "off" icon instead of ``True`` or
+ ``False``.
- * If the string given is a method of the model, ``ModelAdmin`` or a
- callable, Django will HTML-escape the output by default. If you'd rather
- not escape the output of the method, give the method an ``allow_tags``
- attribute whose value is ``True``.
+ * If the string given is a method of the model, ``ModelAdmin`` or a
+ callable, Django will HTML-escape the output by default. If you'd
+ rather not escape the output of the method, give the method an
+ ``allow_tags`` attribute whose value is ``True``.
- Here's a full example model::
+ Here's a full example model::
- class Person(models.Model):
- first_name = models.CharField(max_length=50)
- last_name = models.CharField(max_length=50)
- color_code = models.CharField(max_length=6)
+ class Person(models.Model):
+ first_name = models.CharField(max_length=50)
+ last_name = models.CharField(max_length=50)
+ color_code = models.CharField(max_length=6)
- def colored_name(self):
- return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
- colored_name.allow_tags = True
+ def colored_name(self):
+ return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
+ colored_name.allow_tags = True
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('first_name', 'last_name', 'colored_name')
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'last_name', 'colored_name')
- * If the string given is a method of the model, ``ModelAdmin`` or a
- callable that returns True or False Django will display a pretty "on" or
- "off" icon if you give the method a ``boolean`` attribute whose value is
- ``True``.
+ * If the string given is a method of the model, ``ModelAdmin`` or a
+ callable that returns True or False Django will display a pretty
+ "on" or "off" icon if you give the method a ``boolean`` attribute
+ whose value is ``True``.
- Here's a full example model::
+ Here's a full example model::
- class Person(models.Model):
- first_name = models.CharField(max_length=50)
- birthday = models.DateField()
+ class Person(models.Model):
+ first_name = models.CharField(max_length=50)
+ birthday = models.DateField()
- def born_in_fifties(self):
- return self.birthday.strftime('%Y')[:3] == '195'
- born_in_fifties.boolean = True
+ def born_in_fifties(self):
+ return self.birthday.strftime('%Y')[:3] == '195'
+ born_in_fifties.boolean = True
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('name', 'born_in_fifties')
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('name', 'born_in_fifties')
- * The ``__str__()`` and ``__unicode__()`` methods are just as valid in
- ``list_display`` as any other model method, so it's perfectly OK to do
- this::
+ * The ``__str__()`` and ``__unicode__()`` methods are just as valid in
+ ``list_display`` as any other model method, so it's perfectly OK to
+ do this::
- list_display = ('__unicode__', 'some_other_field')
+ list_display = ('__unicode__', 'some_other_field')
- * Usually, elements of ``list_display`` that aren't actual database fields
- can't be used in sorting (because Django does all the sorting at the
- database level).
+ * Usually, elements of ``list_display`` that aren't actual database
+ fields can't be used in sorting (because Django does all the sorting
+ at the database level).
- However, if an element of ``list_display`` represents a certain database
- field, you can indicate this fact by setting the ``admin_order_field``
- attribute of the item.
+ However, if an element of ``list_display`` represents a certain
+ database field, you can indicate this fact by setting the
+ ``admin_order_field`` attribute of the item.
- For example::
+ For example::
- class Person(models.Model):
- first_name = models.CharField(max_length=50)
- color_code = models.CharField(max_length=6)
+ class Person(models.Model):
+ first_name = models.CharField(max_length=50)
+ color_code = models.CharField(max_length=6)
- def colored_first_name(self):
- return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
- colored_first_name.allow_tags = True
- colored_first_name.admin_order_field = 'first_name'
+ def colored_first_name(self):
+ return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
+ colored_first_name.allow_tags = True
+ colored_first_name.admin_order_field = 'first_name'
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('first_name', 'colored_first_name')
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'colored_first_name')
- The above will tell Django to order by the ``first_name`` field when
- trying to sort by ``colored_first_name`` in the admin.
+ The above will tell Django to order by the ``first_name`` field when
+ trying to sort by ``colored_first_name`` in the admin.
.. attribute:: ModelAdmin.list_display_links
-Set ``list_display_links`` to control which fields in ``list_display`` should
-be linked to the "change" page for an object.
+ Set ``list_display_links`` to control which fields in ``list_display``
+ should be linked to the "change" page for an object.
-By default, the change list page will link the first column -- the first field
-specified in ``list_display`` -- to the change page for each item. But
-``list_display_links`` lets you change which columns are linked. Set
-``list_display_links`` to a list or tuple of field names (in the same format as
-``list_display``) to link.
+ By default, the change list page will link the first column -- the first
+ field specified in ``list_display`` -- to the change page for each item.
+ But``list_display_links`` lets you change which columns are linked. Set
+ ``list_display_links`` to a list or tuple of field names (in the same
+ format as ``list_display``) to link.
-``list_display_links`` can specify one or many field names. As long as the
-field names appear in ``list_display``, Django doesn't care how many (or how
-few) fields are linked. The only requirement is: If you want to use
-``list_display_links``, you must define ``list_display``.
+ ``list_display_links`` can specify one or many field names. As long as the
+ field names appear in ``list_display``, Django doesn't care how many (or
+ how few) fields are linked. The only requirement is: If you want to use
+ ``list_display_links``, you must define ``list_display``.
-In this example, the ``first_name`` and ``last_name`` fields will be linked on
-the change list page::
+ In this example, the ``first_name`` and ``last_name`` fields will be
+ linked on the change list page::
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('first_name', 'last_name', 'birthday')
- list_display_links = ('first_name', 'last_name')
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'last_name', 'birthday')
+ list_display_links = ('first_name', 'last_name')
-.. _admin-list-editable:
+ .. _admin-list-editable:
.. attribute:: ModelAdmin.list_editable
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-Set ``list_editable`` to a list of field names on the model which will allow
-editing on the change list page. That is, fields listed in ``list_editable``
-will be displayed as form widgets on the change list page, allowing users to
-edit and save multiple rows at once.
+ Set ``list_editable`` to a list of field names on the model which will
+ allow editing on the change list page. That is, fields listed in
+ ``list_editable`` will be displayed as form widgets on the change list
+ page, allowing users to edit and save multiple rows at once.
-.. note::
+ .. note::
- ``list_editable`` interacts with a couple of other options in particular
- ways; you should note the following rules:
+ ``list_editable`` interacts with a couple of other options in
+ particular ways; you should note the following rules:
- * Any field in ``list_editable`` must also be in ``list_display``. You
- can't edit a field that's not displayed!
+ * Any field in ``list_editable`` must also be in ``list_display``.
+ You can't edit a field that's not displayed!
- * The same field can't be listed in both ``list_editable`` and
- ``list_display_links`` -- a field can't be both a form and a link.
+ * The same field can't be listed in both ``list_editable`` and
+ ``list_display_links`` -- a field can't be both a form and
+ a link.
- You'll get a validation error if either of these rules are broken.
+ You'll get a validation error if either of these rules are broken.
.. attribute:: ModelAdmin.list_filter
-Set ``list_filter`` to activate filters in the right sidebar of the change list
-page of the admin. This should be a list of field names, and each specified
-field should be either a ``BooleanField``, ``CharField``, ``DateField``,
-``DateTimeField``, ``IntegerField`` or ``ForeignKey``.
+ Set ``list_filter`` to activate filters in the right sidebar of the change
+ list page of the admin. This should be a list of field names, and each
+ specified field should be either a ``BooleanField``, ``CharField``,
+ ``DateField``, ``DateTimeField``, ``IntegerField`` or ``ForeignKey``.
-This example, taken from the ``django.contrib.auth.models.User`` model, shows
-how both ``list_display`` and ``list_filter`` work::
+ This example, taken from the ``django.contrib.auth.models.User`` model,
+ shows how both ``list_display`` and ``list_filter`` work::
- class UserAdmin(admin.ModelAdmin):
- list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
- list_filter = ('is_staff', 'is_superuser')
+ class UserAdmin(admin.ModelAdmin):
+ list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
+ list_filter = ('is_staff', 'is_superuser')
-The above code results in an admin change list page that looks like this:
+ The above code results in an admin change list page that looks like this:
- .. image:: _images/users_changelist.png
+ .. image:: _images/users_changelist.png
-(This example also has ``search_fields`` defined. See below.)
+ (This example also has ``search_fields`` defined. See below.)
.. attribute:: ModelAdmin.list_per_page
-Set ``list_per_page`` to control how many items appear on each paginated admin
-change list page. By default, this is set to ``100``.
+ Set ``list_per_page`` to control how many items appear on each paginated
+ admin change list page. By default, this is set to ``100``.
.. attribute:: ModelAdmin.list_select_related
-Set ``list_select_related`` to tell Django to use
-:meth:`~django.db.models.QuerySet.select_related` in retrieving the list of
-objects on the admin change list page. This can save you a bunch of database
-queries.
+ Set ``list_select_related`` to tell Django to use
+ :meth:`~django.db.models.QuerySet.select_related` in retrieving the list of
+ objects on the admin change list page. This can save you a bunch of
+ database queries.
-The value should be either ``True`` or ``False``. Default is ``False``.
+ The value should be either ``True`` or ``False``. Default is ``False``.
-Note that Django will use :meth:`~django.db.models.QuerySet.select_related`,
-regardless of this setting, if one of the ``list_display`` fields is a
-``ForeignKey``.
+ Note that Django will use :meth:`~django.db.models.QuerySet.select_related`,
+ regardless of this setting, if one of the ``list_display`` fields is a
+ ``ForeignKey``.
.. attribute:: ModelAdmin.inlines
-See ``InlineModelAdmin`` objects below.
+ See ``InlineModelAdmin`` objects below.
.. attribute:: ModelAdmin.ordering
-Set ``ordering`` to specify how lists of objects should be ordered in the
-Django admin views. This should be a list or tuple in the same format as a
-model's ``ordering`` parameter.
+ Set ``ordering`` to specify how lists of objects should be ordered in the
+ Django admin views. This should be a list or tuple in the same format as a
+ model's ``ordering`` parameter.
-If this isn't provided, the Django admin will use the model's default ordering.
+ If this isn't provided, the Django admin will use the model's default
+ ordering.
-.. admonition:: Note
+ .. admonition:: Note
- Django will only honor the first element in the list/tuple; any others
- will be ignored.
+ Django will only honor the first element in the list/tuple; any others
+ will be ignored.
.. attribute:: ModelAdmin.prepopulated_fields
-Set ``prepopulated_fields`` to a dictionary mapping field names to the fields
-it should prepopulate from::
+ Set ``prepopulated_fields`` to a dictionary mapping field names to the
+ fields it should prepopulate from::
- class ArticleAdmin(admin.ModelAdmin):
- prepopulated_fields = {"slug": ("title",)}
+ class ArticleAdmin(admin.ModelAdmin):
+ prepopulated_fields = {"slug": ("title",)}
-When set, the given fields will use a bit of JavaScript to populate from the
-fields assigned. The main use for this functionality is to automatically
-generate the value for ``SlugField`` fields from one or more other fields. The
-generated value is produced by concatenating the values of the source fields,
-and then by transforming that result into a valid slug (e.g. substituting
-dashes for spaces).
+ When set, the given fields will use a bit of JavaScript to populate from
+ the fields assigned. The main use for this functionality is to
+ automatically generate the value for ``SlugField`` fields from one or more
+ other fields. The generated value is produced by concatenating the values
+ of the source fields, and then by transforming that result into a valid
+ slug (e.g. substituting dashes for spaces).
-``prepopulated_fields`` doesn't accept ``DateTimeField``, ``ForeignKey``, nor
-``ManyToManyField`` fields.
+ ``prepopulated_fields`` doesn't accept ``DateTimeField``, ``ForeignKey``,
+ nor ``ManyToManyField`` fields.
.. attribute:: ModelAdmin.radio_fields
-By default, Django's admin uses a select-box interface (<select>) for
-fields that are ``ForeignKey`` or have ``choices`` set. If a field is present
-in ``radio_fields``, Django will use a radio-button interface instead.
-Assuming ``group`` is a ``ForeignKey`` on the ``Person`` model::
+ By default, Django's admin uses a select-box interface (<select>) for
+ fields that are ``ForeignKey`` or have ``choices`` set. If a field is
+ present in ``radio_fields``, Django will use a radio-button interface
+ instead. Assuming ``group`` is a ``ForeignKey`` on the ``Person`` model::
- class PersonAdmin(admin.ModelAdmin):
- radio_fields = {"group": admin.VERTICAL}
+ class PersonAdmin(admin.ModelAdmin):
+ radio_fields = {"group": admin.VERTICAL}
-You have the choice of using ``HORIZONTAL`` or ``VERTICAL`` from the
-``django.contrib.admin`` module.
+ You have the choice of using ``HORIZONTAL`` or ``VERTICAL`` from the
+ ``django.contrib.admin`` module.
-Don't include a field in ``radio_fields`` unless it's a ``ForeignKey`` or has
-``choices`` set.
+ Don't include a field in ``radio_fields`` unless it's a ``ForeignKey`` or has
+ ``choices`` set.
.. attribute:: ModelAdmin.raw_id_fields
-By default, Django's admin uses a select-box interface (<select>) for
-fields that are ``ForeignKey``. Sometimes you don't want to incur the
-overhead of having to select all the related instances to display in the
-drop-down.
+ By default, Django's admin uses a select-box interface (<select>) for
+ fields that are ``ForeignKey``. Sometimes you don't want to incur the
+ overhead of having to select all the related instances to display in the
+ drop-down.
-``raw_id_fields`` is a list of fields you would like to change
-into a ``Input`` widget for either a ``ForeignKey`` or ``ManyToManyField``::
+ ``raw_id_fields`` is a list of fields you would like to change
+ into a ``Input`` widget for either a ``ForeignKey`` or
+ ``ManyToManyField``::
- class ArticleAdmin(admin.ModelAdmin):
- raw_id_fields = ("newspaper",)
+ class ArticleAdmin(admin.ModelAdmin):
+ raw_id_fields = ("newspaper",)
.. attribute:: ModelAdmin.readonly_fields
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-By default the admin shows all fields as editable. Any fields in this option
-(which should be a ``list`` or ``tuple``) will display its data as-is and
-non-editable. This option behaves nearly identical to :attr:`ModelAdmin.list_display`.
-Usage is the same, however, when you specify :attr:`ModelAdmin.fields` or
-:attr:`ModelAdmin.fieldsets` the read-only fields must be present to be shown
-(they are ignored otherwise).
+ By default the admin shows all fields as editable. Any fields in this
+ option (which should be a ``list`` or ``tuple``) will display its data
+ as-is and non-editable. This option behaves nearly identical to
+ :attr:`ModelAdmin.list_display`. Usage is the same, however, when you
+ specify :attr:`ModelAdmin.fields` or :attr:`ModelAdmin.fieldsets` the
+ read-only fields must be present to be shown (they are ignored otherwise).
-If ``readonly_fields`` is used without defining explicit ordering through
-:attr:`ModelAdmin.fields` or :attr:`ModelAdmin.fieldsets` they will be added
-last after all editable fields.
+ If ``readonly_fields`` is used without defining explicit ordering through
+ :attr:`ModelAdmin.fields` or :attr:`ModelAdmin.fieldsets` they will be
+ added last after all editable fields.
.. attribute:: ModelAdmin.save_as
-Set ``save_as`` to enable a "save as" feature on admin change forms.
+ Set ``save_as`` to enable a "save as" feature on admin change forms.
-Normally, objects have three save options: "Save", "Save and continue editing"
-and "Save and add another". If ``save_as`` is ``True``, "Save and add another"
-will be replaced by a "Save as" button.
+ Normally, objects have three save options: "Save", "Save and continue
+ editing" and "Save and add another". If ``save_as`` is ``True``, "Save
+ and add another" will be replaced by a "Save as" button.
-"Save as" means the object will be saved as a new object (with a new ID),
-rather than the old object.
+ "Save as" means the object will be saved as a new object (with a new ID),
+ rather than the old object.
-By default, ``save_as`` is set to ``False``.
+ By default, ``save_as`` is set to ``False``.
.. attribute:: ModelAdmin.save_on_top
-Set ``save_on_top`` to add save buttons across the top of your admin change
-forms.
+ Set ``save_on_top`` to add save buttons across the top of your adminchange
+ forms.
-Normally, the save buttons appear only at the bottom of the forms. If you set
-``save_on_top``, the buttons will appear both on the top and the bottom.
+ Normally, the save buttons appear only at the bottom of the forms. If you
+ set ``save_on_top``, the buttons will appear both on the top and the
+ bottom.
By default, ``save_on_top`` is set to ``False``.
.. attribute:: ModelAdmin.search_fields
-Set ``search_fields`` to enable a search box on the admin change list page.
-This should be set to a list of field names that will be searched whenever
-somebody submits a search query in that text box.
+ Set ``search_fields`` to enable a search box on the admin change list page.
+ This should be set to a list of field names that will be searched whenever
+ somebody submits a search query in that text box.
-These fields should be some kind of text field, such as ``CharField`` or
-``TextField``. You can also perform a related lookup on a ``ForeignKey`` or
-``ManyToManyField`` with the lookup API "follow" notation::
+ These fields should be some kind of text field, such as ``CharField`` or
+ ``TextField``. You can also perform a related lookup on a ``ForeignKey`` or
+ ``ManyToManyField`` with the lookup API "follow" notation::
- search_fields = ['foreign_key__related_fieldname']
+ search_fields = ['foreign_key__related_fieldname']
-For example, if you have a blog entry with an author, the following definition
-would enable search blog entries by the email address of the author::
+ For example, if you have a blog entry with an author, the following
+ definition would enable search blog entries by the email address of the
+ author::
- search_fields = ['user__email']
+ search_fields = ['user__email']
-When somebody does a search in the admin search box, Django splits the search
-query into words and returns all objects that contain each of the words, case
-insensitive, where each word must be in at least one of ``search_fields``. For
-example, if ``search_fields`` is set to ``['first_name', 'last_name']`` and a
-user searches for ``john lennon``, Django will do the equivalent of this SQL
-``WHERE`` clause::
+ When somebody does a search in the admin search box, Django splits the
+ search query into words and returns all objects that contain each of the
+ words, case insensitive, where each word must be in at least one of
+ ``search_fields``. For example, if ``search_fields`` is set to
+ ``['first_name', 'last_name']`` and a user searches for ``john lennon``,
+ Django will do the equivalent of this SQL ``WHERE`` clause::
- WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
- AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
+ WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
+ AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
-For faster and/or more restrictive searches, prefix the field name
-with an operator:
+ For faster and/or more restrictive searches, prefix the field name
+ with an operator:
-``^``
- Matches the beginning of the field. For example, if ``search_fields`` is
- set to ``['^first_name', '^last_name']`` and a user searches for
- ``john lennon``, Django will do the equivalent of this SQL ``WHERE``
- clause::
+ ``^``
+ Matches the beginning of the field. For example, if ``search_fields``
+ is set to ``['^first_name', '^last_name']`` and a user searches for
+ ``john lennon``, Django will do the equivalent of this SQL ``WHERE``
+ clause::
- WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
- AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
+ WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
+ AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
- This query is more efficient than the normal ``'%john%'`` query, because
- the database only needs to check the beginning of a column's data, rather
- than seeking through the entire column's data. Plus, if the column has an
- index on it, some databases may be able to use the index for this query,
- even though it's a ``LIKE`` query.
+ This query is more efficient than the normal ``'%john%'`` query,
+ because the database only needs to check the beginning of a column's
+ data, rather than seeking through the entire column's data. Plus, if
+ the column has an index on it, some databases may be able to use the
+ index for this query, even though it's a ``LIKE`` query.
-``=``
- Matches exactly, case-insensitive. For example, if
- ``search_fields`` is set to ``['=first_name', '=last_name']`` and
- a user searches for ``john lennon``, Django will do the equivalent
- of this SQL ``WHERE`` clause::
+ ``=``
+ Matches exactly, case-insensitive. For example, if
+ ``search_fields`` is set to ``['=first_name', '=last_name']`` and
+ a user searches for ``john lennon``, Django will do the equivalent
+ of this SQL ``WHERE`` clause::
- WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
- AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
+ WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
+ AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
- Note that the query input is split by spaces, so, following this example,
- it's currently not possible to search for all records in which
- ``first_name`` is exactly ``'john winston'`` (containing a space).
+ Note that the query input is split by spaces, so, following this
+ example, it's currently not possible to search for all records in which
+ ``first_name`` is exactly ``'john winston'`` (containing a space).
-``@``
- Performs a full-text match. This is like the default search method but uses
- an index. Currently this is only available for MySQL.
+ ``@``
+ Performs a full-text match. This is like the default search method but
+ uses an index. Currently this is only available for MySQL.
.. attribute:: ModelAdmin.formfield_overrides
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-This provides a quick-and-dirty way to override some of the
-:class:`~django.forms.Field` options for use in the admin.
-``formfield_overrides`` is a dictionary mapping a field class to a dict of
-arguments to pass to the field at construction time.
+ This provides a quick-and-dirty way to override some of the
+ :class:`~django.forms.Field` options for use in the admin.
+ ``formfield_overrides`` is a dictionary mapping a field class to a dict of
+ arguments to pass to the field at construction time.
-Since that's a bit abstract, let's look at a concrete example. The most common
-use of ``formfield_overrides`` is to add a custom widget for a certain type of
-field. So, imagine we've written a ``RichTextEditorWidget`` that we'd like to
-use for large text fields instead of the default ``<textarea>``. Here's how we'd
-do that::
+ Since that's a bit abstract, let's look at a concrete example. The most
+ common use of ``formfield_overrides`` is to add a custom widget for a
+ certain type of field. So, imagine we've written a ``RichTextEditorWidget``
+ that we'd like to use for large text fields instead of the default
+ ``<textarea>``. Here's how we'd do that::
- from django.db import models
- from django.contrib import admin
+ from django.db import models
+ from django.contrib import admin
- # Import our custom widget and our model from where they're defined
- from myapp.widgets import RichTextEditorWidget
- from myapp.models import MyModel
+ # Import our custom widget and our model from where they're defined
+ from myapp.widgets import RichTextEditorWidget
+ from myapp.models import MyModel
- class MyModelAdmin(admin.ModelAdmin):
- formfield_overrides = {
- models.TextField: {'widget': RichTextEditorWidget},
- }
+ class MyModelAdmin(admin.ModelAdmin):
+ formfield_overrides = {
+ models.TextField: {'widget': RichTextEditorWidget},
+ }
-Note that the key in the dictionary is the actual field class, *not* a string.
-The value is another dictionary; these arguments will be passed to
-:meth:`~django.forms.Field.__init__`. See :doc:`/ref/forms/api` for details.
+ Note that the key in the dictionary is the actual field class, *not* a
+ string. The value is another dictionary; these arguments will be passed to
+ :meth:`~django.forms.Field.__init__`. See :doc:`/ref/forms/api` for
+ details.
-.. warning::
+ .. warning::
- If you want to use a custom widget with a relation field (i.e.
- :class:`~django.db.models.ForeignKey` or
- :class:`~django.db.models.ManyToManyField`), make sure you haven't included
- that field's name in ``raw_id_fields`` or ``radio_fields``.
+ If you want to use a custom widget with a relation field (i.e.
+ :class:`~django.db.models.ForeignKey` or
+ :class:`~django.db.models.ManyToManyField`), make sure you haven't included
+ that field's name in ``raw_id_fields`` or ``radio_fields``.
- ``formfield_overrides`` won't let you change the widget on relation fields
- that have ``raw_id_fields`` or ``radio_fields`` set. That's because
- ``raw_id_fields`` and ``radio_fields`` imply custom widgets of their own.
+ ``formfield_overrides`` won't let you change the widget on relation
+ fields that have ``raw_id_fields`` or ``radio_fields`` set. That's
+ because ``raw_id_fields`` and ``radio_fields`` imply custom widgets of
+ their own.
.. attribute:: ModelAdmin.actions
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-A list of actions to make available on the change list page. See
-:doc:`/ref/contrib/admin/actions` for details.
+ A list of actions to make available on the change list page. See
+ :doc:`/ref/contrib/admin/actions` for details.
.. attribute:: ModelAdmin.actions_on_top
.. attribute:: ModelAdmin.actions_on_bottom
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-Controls where on the page the actions bar appears. By default, the admin
-changelist displays actions at the top of the page (``actions_on_top = True;
-actions_on_bottom = False``).
+ Controls where on the page the actions bar appears. By default, the admin
+ changelist displays actions at the top of the page (``actions_on_top = True;
+ actions_on_bottom = False``).
.. attribute:: ModelAdmin.actions_selection_counter
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-Controls whether a selection counter is display next to the action dropdown.
-By default, the admin changelist will display it
-(``actions_selection_counter = True``).
+ Controls whether a selection counter is display next to the action dropdown.
+ By default, the admin changelist will display it
+ (``actions_selection_counter = True``).
Custom template options
~~~~~~~~~~~~~~~~~~~~~~~
@@ -759,133 +770,136 @@ templates used by the :class:`ModelAdmin` views:
.. method:: ModelAdmin.save_model(self, request, obj, form, change)
-The ``save_model`` method is given the ``HttpRequest``, a model instance,
-a ``ModelForm`` instance and a boolean value based on whether it is adding or
-changing the object. Here you can do any pre- or post-save operations.
+ The ``save_model`` method is given the ``HttpRequest``, a model instance,
+ a ``ModelForm`` instance and a boolean value based on whether it is adding
+ or changing the object. Here you can do any pre- or post-save operations.
-For example to attach ``request.user`` to the object prior to saving::
+ For example to attach ``request.user`` to the object prior to saving::
- class ArticleAdmin(admin.ModelAdmin):
- def save_model(self, request, obj, form, change):
- obj.user = request.user
- obj.save()
+ class ArticleAdmin(admin.ModelAdmin):
+ def save_model(self, request, obj, form, change):
+ obj.user = request.user
+ obj.save()
.. method:: ModelAdmin.save_formset(self, request, form, formset, change)
-The ``save_formset`` method is given the ``HttpRequest``, the parent
-``ModelForm`` instance and a boolean value based on whether it is adding or
-changing the parent object.
+ The ``save_formset`` method is given the ``HttpRequest``, the parent
+ ``ModelForm`` instance and a boolean value based on whether it is adding or
+ changing the parent object.
-For example to attach ``request.user`` to each changed formset
-model instance::
+ For example to attach ``request.user`` to each changed formset
+ model instance::
- class ArticleAdmin(admin.ModelAdmin):
- def save_formset(self, request, form, formset, change):
- instances = formset.save(commit=False)
- for instance in instances:
- instance.user = request.user
- instance.save()
- formset.save_m2m()
+ class ArticleAdmin(admin.ModelAdmin):
+ def save_formset(self, request, form, formset, change):
+ instances = formset.save(commit=False)
+ for instance in instances:
+ instance.user = request.user
+ instance.save()
+ formset.save_m2m()
.. method:: ModelAdmin.get_readonly_fields(self, request, obj=None)
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-The ``get_readonly_fields`` method is given the ``HttpRequest`` and the
-``obj`` being edited (or ``None`` on an add form) and is expected to return a
-``list`` or ``tuple`` of field names that will be displayed as read-only, as
-described above in the :attr:`ModelAdmin.readonly_fields` section.
+ The ``get_readonly_fields`` method is given the ``HttpRequest`` and the
+ ``obj`` being edited (or ``None`` on an add form) and is expected to return
+ a ``list`` or ``tuple`` of field names that will be displayed as read-only,
+ as described above in the :attr:`ModelAdmin.readonly_fields` section.
.. method:: ModelAdmin.get_urls(self)
-.. versionadded:: 1.1
-
-The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
-that ModelAdmin in the same way as a URLconf. Therefore you can extend them as
-documented in :doc:`/topics/http/urls`::
-
- class MyModelAdmin(admin.ModelAdmin):
- def get_urls(self):
- urls = super(MyModelAdmin, self).get_urls()
- my_urls = patterns('',
- (r'^my_view/$', self.my_view)
- )
- return my_urls + urls
-
-.. note::
+ .. versionadded:: 1.1
- Notice that the custom patterns are included *before* the regular admin
- URLs: the admin URL patterns are very permissive and will match nearly
- anything, so you'll usually want to prepend your custom URLs to the built-in
- ones.
+ The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
+ that ModelAdmin in the same way as a URLconf. Therefore you can extend
+ them as documented in :doc:`/topics/http/urls`::
-However, the ``self.my_view`` function registered above suffers from two
-problems:
-
- * It will *not* perform any permission checks, so it will be accessible to
- the general public.
- * It will *not* provide any header details to prevent caching. This means if
- the page retrieves data from the database, and caching middleware is
- active, the page could show outdated information.
-
-Since this is usually not what you want, Django provides a convenience wrapper
-to check permissions and mark the view as non-cacheable. This wrapper is
-:meth:`AdminSite.admin_view` (i.e. ``self.admin_site.admin_view`` inside a
-``ModelAdmin`` instance); use it like so::
+ class MyModelAdmin(admin.ModelAdmin):
+ def get_urls(self):
+ urls = super(MyModelAdmin, self).get_urls()
+ my_urls = patterns('',
+ (r'^my_view/$', self.my_view)
+ )
+ return my_urls + urls
+
+ .. note::
+
+ Notice that the custom patterns are included *before* the regular admin
+ URLs: the admin URL patterns are very permissive and will match nearly
+ anything, so you'll usually want to prepend your custom URLs to the
+ built-in ones.
+
+ However, the ``self.my_view`` function registered above suffers from two
+ problems:
+
+ * It will *not* perform any permission checks, so it will be accessible
+ to the general public.
+ * It will *not* provide any header details to prevent caching. This means
+ if the page retrieves data from the database, and caching middleware is
+ active, the page could show outdated information.
+
+ Since this is usually not what you want, Django provides a convenience
+ wrapper to check permissions and mark the view as non-cacheable. This
+ wrapper is :meth:`AdminSite.admin_view` (i.e.
+ ``self.admin_site.admin_view`` inside a ``ModelAdmin`` instance); use it
+ like so::
- class MyModelAdmin(admin.ModelAdmin):
- def get_urls(self):
- urls = super(MyModelAdmin, self).get_urls()
- my_urls = patterns('',
- (r'^my_view/$', self.admin_site.admin_view(self.my_view))
- )
- return my_urls + urls
+ class MyModelAdmin(admin.ModelAdmin):
+ def get_urls(self):
+ urls = super(MyModelAdmin, self).get_urls()
+ my_urls = patterns('',
+ (r'^my_view/$', self.admin_site.admin_view(self.my_view))
+ )
+ return my_urls + urls
-Notice the wrapped view in the fifth line above::
+ Notice the wrapped view in the fifth line above::
- (r'^my_view/$', self.admin_site.admin_view(self.my_view))
+ (r'^my_view/$', self.admin_site.admin_view(self.my_view))
-This wrapping will protect ``self.my_view`` from unauthorized access and will
-apply the ``django.views.decorators.cache.never_cache`` decorator to make sure
-it is not cached if the cache middleware is active.
+ This wrapping will protect ``self.my_view`` from unauthorized access and
+ will apply the ``django.views.decorators.cache.never_cache`` decorator to
+ make sure it is not cached if the cache middleware is active.
-If the page is cacheable, but you still want the permission check to be performed,
-you can pass a ``cacheable=True`` argument to :meth:`AdminSite.admin_view`::
+ If the page is cacheable, but you still want the permission check to be
+ performed, you can pass a ``cacheable=True`` argument to
+ :meth:`AdminSite.admin_view`::
- (r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))
+ (r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))
.. method:: ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs)
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-The ``formfield_for_foreignkey`` method on a ``ModelAdmin`` allows you to
-override the default formfield for a foreign key field. For example, to
-return a subset of objects for this foreign key field based on the user::
+ The ``formfield_for_foreignkey`` method on a ``ModelAdmin`` allows you to
+ override the default formfield for a foreign key field. For example, to
+ return a subset of objects for this foreign key field based on the user::
- class MyModelAdmin(admin.ModelAdmin):
- def formfield_for_foreignkey(self, db_field, request, **kwargs):
- if db_field.name == "car":
- kwargs["queryset"] = Car.objects.filter(owner=request.user)
- return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+ class MyModelAdmin(admin.ModelAdmin):
+ def formfield_for_foreignkey(self, db_field, request, **kwargs):
+ if db_field.name == "car":
+ kwargs["queryset"] = Car.objects.filter(owner=request.user)
+ return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
-This uses the ``HttpRequest`` instance to filter the ``Car`` foreign key field
-to only display the cars owned by the ``User`` instance.
+ This uses the ``HttpRequest`` instance to filter the ``Car`` foreign key
+ field to only display the cars owned by the ``User`` instance.
.. method:: ModelAdmin.formfield_for_manytomany(self, db_field, request, **kwargs)
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-Like the ``formfield_for_foreignkey`` method, the ``formfield_for_manytomany``
-method can be overridden to change the default formfield for a many to many
-field. For example, if an owner can own multiple cars and cars can belong
-to multiple owners -- a many to many relationship -- you could filter the
-``Car`` foreign key field to only display the cars owned by the ``User``::
+ Like the ``formfield_for_foreignkey`` method, the
+ ``formfield_for_manytomany`` method can be overridden to change the
+ default formfield for a many to many field. For example, if an owner can
+ own multiple cars and cars can belong to multiple owners -- a many to
+ many relationship -- you could filter the ``Car`` foreign key field to
+ only display the cars owned by the ``User``::
- class MyModelAdmin(admin.ModelAdmin):
- def formfield_for_manytomany(self, db_field, request, **kwargs):
- if db_field.name == "cars":
- kwargs["queryset"] = Car.objects.filter(owner=request.user)
- return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
+ class MyModelAdmin(admin.ModelAdmin):
+ def formfield_for_manytomany(self, db_field, request, **kwargs):
+ if db_field.name == "cars":
+ kwargs["queryset"] = Car.objects.filter(owner=request.user)
+ return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
.. method:: ModelAdmin.formfield_for_choice_field(self, db_field, request, **kwargs)
@@ -929,17 +943,17 @@ to multiple owners -- a many to many relationship -- you could filter the
.. method:: ModelAdmin.queryset(self, request)
-The ``queryset`` method on a ``ModelAdmin`` returns a
-:class:`~django.db.models.QuerySet` of all model instances that can be
-edited by the admin site. One use case for overriding this method is
-to show objects owned by the logged-in user::
+ The ``queryset`` method on a ``ModelAdmin`` returns a
+ :class:`~django.db.models.QuerySet` of all model instances that can be
+ edited by the admin site. One use case for overriding this method is
+ to show objects owned by the logged-in user::
- class MyModelAdmin(admin.ModelAdmin):
- def queryset(self, request):
- qs = super(MyModelAdmin, self).queryset(request)
- if request.user.is_superuser:
- return qs
- return qs.filter(author=request.user)
+ class MyModelAdmin(admin.ModelAdmin):
+ def queryset(self, request):
+ qs = super(MyModelAdmin, self).queryset(request)
+ if request.user.is_superuser:
+ return qs
+ return qs.filter(author=request.user)
.. method:: ModelAdmin.message_user(request, message)
@@ -952,24 +966,26 @@ Other methods
.. method:: ModelAdmin.add_view(self, request, form_url='', extra_context=None)
-Django view for the model instance addition page. See note below.
+ Django view for the model instance addition page. See note below.
.. method:: ModelAdmin.change_view(self, request, object_id, extra_context=None)
-Django view for the model instance edition page. See note below.
+ Django view for the model instance edition page. See note below.
.. method:: ModelAdmin.changelist_view(self, request, extra_context=None)
-Django view for the model instances change list/actions page. See note below.
+ Django view for the model instances change list/actions page. See note
+ below.
.. method:: ModelAdmin.delete_view(self, request, object_id, extra_context=None)
-Django view for the model instance(s) deletion confirmation page. See note below.
+ Django view for the model instance(s) deletion confirmation page. See note
+ below.
.. method:: ModelAdmin.history_view(self, request, object_id, extra_context=None)
-Django view for the page that shows the modification history for a given model
-instance.
+ Django view for the page that shows the modification history for a given
+ model instance.
Unlike the hook-type ``ModelAdmin`` methods detailed in the previous section,
these five methods are in reality designed to be invoked as Django views from
@@ -1025,9 +1041,9 @@ JavaScript without including a second copy, you can use the
Adding custom validation to the admin
-------------------------------------
-Adding custom validation of data in the admin is quite easy. The automatic admin
-interface reuses :mod:`django.forms`, and the ``ModelAdmin`` class gives you
-the ability define your own form::
+Adding custom validation of data in the admin is quite easy. The automatic
+admin interface reuses :mod:`django.forms`, and the ``ModelAdmin`` class gives
+you the ability define your own form::
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
@@ -1044,8 +1060,8 @@ any field::
# do something that validates your data
return self.cleaned_data["name"]
-It is important you use a ``ModelForm`` here otherwise things can break. See the
-:doc:`forms </ref/forms/index>` documentation on :doc:`custom validation
+It is important you use a ``ModelForm`` here otherwise things can break. See
+the :doc:`forms </ref/forms/index>` documentation on :doc:`custom validation
</ref/forms/validation>` and, more specifically, the
:ref:`model form validation notes <overriding-modelform-clean-method>` for more
information.
@@ -1057,33 +1073,34 @@ information.
.. class:: InlineModelAdmin
-The admin interface has the ability to edit models on the same page as a
-parent model. These are called inlines. Suppose you have these two models::
+ The admin interface has the ability to edit models on the same page as a
+ parent model. These are called inlines. Suppose you have these two models::
- class Author(models.Model):
- name = models.CharField(max_length=100)
+ class Author(models.Model):
+ name = models.CharField(max_length=100)
- class Book(models.Model):
- author = models.ForeignKey(Author)
- title = models.CharField(max_length=100)
+ class Book(models.Model):
+ author = models.ForeignKey(Author)
+ title = models.CharField(max_length=100)
-You can edit the books authored by an author on the author page. You add
-inlines to a model by specifying them in a ``ModelAdmin.inlines``::
+ You can edit the books authored by an author on the author page. You add
+ inlines to a model by specifying them in a ``ModelAdmin.inlines``::
- class BookInline(admin.TabularInline):
- model = Book
+ class BookInline(admin.TabularInline):
+ model = Book
- class AuthorAdmin(admin.ModelAdmin):
- inlines = [
- BookInline,
- ]
+ class AuthorAdmin(admin.ModelAdmin):
+ inlines = [
+ BookInline,
+ ]
-Django provides two subclasses of ``InlineModelAdmin`` and they are:
+ Django provides two subclasses of ``InlineModelAdmin`` and they are:
- * ``TabularInline``
- * ``StackedInline``
+ * ``TabularInline``
+ * ``StackedInline``
-The difference between these two is merely the template used to render them.
+ The difference between these two is merely the template used to render
+ them.
``InlineModelAdmin`` options
-----------------------------
@@ -1140,9 +1157,10 @@ The ``InlineModelAdmin`` class adds:
.. attribute:: InlineModelAdmin.extra
- This controls the number of extra forms the formset will display in addition
- to the initial forms. See the
- :doc:`formsets documentation </topics/forms/formsets>` for more information.
+ This controls the number of extra forms the formset will display in
+ addition to the initial forms. See the
+ :doc:`formsets documentation </topics/forms/formsets>` for more
+ information.
.. versionadded:: 1.2
@@ -1153,7 +1171,7 @@ The ``InlineModelAdmin`` class adds:
The dynamic link will not appear if the number of currently displayed forms
exceeds ``max_num``, or if the user does not have JavaScript enabled.
-.. _ref-contrib-admin-inline-max-num:
+ .. _ref-contrib-admin-inline-max-num:
.. attribute:: InlineModelAdmin.max_num
@@ -1375,8 +1393,8 @@ Overriding Admin Templates
==========================
It is relatively easy to override many of the templates which the admin module
-uses to generate the various pages of an admin site. You can even override a few
-of these templates for a specific app, or a specific model.
+uses to generate the various pages of an admin site. You can even override a
+few of these templates for a specific app, or a specific model.
Set up your projects admin template directories
-----------------------------------------------
@@ -1384,15 +1402,15 @@ Set up your projects admin template directories
The admin template files are located in the ``contrib/admin/templates/admin``
directory.
-In order to override one or more of them, first create an ``admin`` directory in
-your project's ``templates`` directory. This can be any of the directories you
-specified in ``TEMPLATE_DIRS``.
+In order to override one or more of them, first create an ``admin`` directory
+in your project's ``templates`` directory. This can be any of the directories
+you specified in ``TEMPLATE_DIRS``.
Within this ``admin`` directory, create sub-directories named after your app.
Within these app subdirectories create sub-directories named after your models.
Note, that the admin app will lowercase the model name when looking for the
-directory, so make sure you name the directory in all lowercase if you are going
-to run your app on a case-sensitive filesystem.
+directory, so make sure you name the directory in all lowercase if you are
+going to run your app on a case-sensitive filesystem.
To override an admin template for a specific app, copy and edit the template
from the ``django/contrib/admin/templates/admin`` directory, and save it to one
@@ -1462,8 +1480,9 @@ and 500 pages.
Some of the admin templates, such as ``change_list_request.html`` are used
to render custom inclusion tags. These may be overridden, but in such cases
- you are probably better off creating your own version of the tag in question
- and giving it a different name. That way you can use it selectively.
+ you are probably better off creating your own version of the tag in
+ question and giving it a different name. That way you can use it
+ selectively.
Root and login templates
------------------------
@@ -1478,25 +1497,25 @@ creating your own ``AdminSite`` instance (see below), and changing the
.. class:: AdminSite(name=None)
-A Django administrative site is represented by an instance of
-``django.contrib.admin.sites.AdminSite``; by default, an instance of
-this class is created as ``django.contrib.admin.site`` and you can
-register your models and ``ModelAdmin`` instances with it.
+ A Django administrative site is represented by an instance of
+ ``django.contrib.admin.sites.AdminSite``; by default, an instance of
+ this class is created as ``django.contrib.admin.site`` and you can
+ register your models and ``ModelAdmin`` instances with it.
-If you'd like to set up your own administrative site with custom
-behavior, however, you're free to subclass ``AdminSite`` and override
-or add anything you like. Then, simply create an instance of your
-``AdminSite`` subclass (the same way you'd instantiate any other
-Python class), and register your models and ``ModelAdmin`` subclasses
-with it instead of using the default.
+ If you'd like to set up your own administrative site with custom
+ behavior, however, you're free to subclass ``AdminSite`` and override
+ or add anything you like. Then, simply create an instance of your
+ ``AdminSite`` subclass (the same way you'd instantiate any other
+ Python class), and register your models and ``ModelAdmin`` subclasses
+ with it instead of using the default.
-.. versionadded:: 1.1
+ .. versionadded:: 1.1
-When constructing an instance of an ``AdminSite``, you are able to provide
-a unique instance name using the ``name`` argument to the constructor. This
-instance name is used to identify the instance, especially when
-:ref:`reversing admin URLs <admin-reverse-urls>`. If no instance name is
-provided, a default instance name of ``admin`` will be used.
+ When constructing an instance of an ``AdminSite``, you are able to provide
+ a unique instance name using the ``name`` argument to the constructor. This
+ instance name is used to identify the instance, especially when
+ :ref:`reversing admin URLs <admin-reverse-urls>`. If no instance name is
+ provided, a default instance name of ``admin`` will be used.
``AdminSite`` attributes
------------------------
@@ -1506,31 +1525,32 @@ Templates can override or extend base admin templates as described in
.. attribute:: AdminSite.index_template
-Path to a custom template that will be used by the admin site main index view.
+ Path to a custom template that will be used by the admin site main index
+ view.
.. attribute:: AdminSite.login_template
-Path to a custom template that will be used by the admin site login view.
+ Path to a custom template that will be used by the admin site login view.
.. attribute:: AdminSite.logout_template
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-Path to a custom template that will be used by the admin site logout view.
+ Path to a custom template that will be used by the admin site logout view.
.. attribute:: AdminSite.password_change_template
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-Path to a custom template that will be used by the admin site password change
-view.
+ Path to a custom template that will be used by the admin site password
+ change view.
.. attribute:: AdminSite.password_change_done_template
-.. versionadded:: 1.2
+ .. versionadded:: 1.2
-Path to a custom template that will be used by the admin site password change
-done view.
+ Path to a custom template that will be used by the admin site password
+ change done view.
Hooking ``AdminSite`` instances into your URLconf
-------------------------------------------------
@@ -1665,12 +1685,14 @@ call::
>>> c = Choice.objects.get(...)
>>> change_url = urlresolvers.reverse('admin:polls_choice_change', args=(c.id,))
-This will find the first registered instance of the admin application (whatever the instance
-name), and resolve to the view for changing ``poll.Choice`` instances in that instance.
+This will find the first registered instance of the admin application
+(whatever the instance name), and resolve to the view for changing
+``poll.Choice`` instances in that instance.
-If you want to find a URL in a specific admin instance, provide the name of that instance
-as a ``current_app`` hint to the reverse call. For example, if you specifically wanted
-the admin view from the admin instance named ``custom``, you would need to call::
+If you want to find a URL in a specific admin instance, provide the name of
+that instance as a ``current_app`` hint to the reverse call. For example,
+if you specifically wanted the admin view from the admin instance named
+``custom``, you would need to call::
>>> change_url = urlresolvers.reverse('custom:polls_choice_change', args=(c.id,))
Please sign in to comment.
Something went wrong with that request. Please try again.