diff options
| author | Gabriel Hurley <gabehr@gmail.com> | 2010-12-05 04:52:31 +0000 |
|---|---|---|
| committer | Gabriel Hurley <gabehr@gmail.com> | 2010-12-05 04:52:31 +0000 |
| commit | 01f2081bb6145c9b6d12aee9a5ec36fc7649efcf (patch) | |
| tree | a07615e7cdc0a1d10cfdd4373b733393567f7aca | |
| parent | 4a1f2129d09658e705fbe0660275c6efccf1474a (diff) | |
Fixed #14835 -- Corrected a lack of indentation in the reST markup for docs/ref/contrib/admin/index.txt and reflowed the text accordingly. Thanks to cogat for the report.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14830 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | docs/ref/contrib/admin/index.txt | 1220 |
1 files changed, 621 insertions, 599 deletions
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 15a5ba2c55..4c72cf127d 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -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,624 +99,634 @@ 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. + 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.) + ``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. + 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:: + A full example, taken from the :class:`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') - }), - ) + 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 -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 -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 -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') -Fields in ``list_filter`` can also span relations using the ``__`` lookup:: + Fields in ``list_filter`` can also span relations using the ``__`` lookup:: - class UserAdminWithLookup(UserAdmin): - list_filter = ('groups__name') + class UserAdminWithLookup(UserAdmin): + list_filter = ('groups__name') -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 :class:`InlineModelAdmin` objects below. .. attribute:: ModelAdmin.ordering -Set ``ordering`` to specify how objects on the admin change list page should be -ordered. This should be a list or tuple in the same format as a model's -``ordering`` parameter. + Set ``ordering`` to specify how objects on the admin change list page + should be ordered. 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 an ``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 admin change + 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``. + 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 ~~~~~~~~~~~~~~~~~~~~~~~ @@ -770,178 +781,183 @@ 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.delete_model(self, request, obj) -.. versionadded:: 1.3 + .. versionadded:: 1.3 -The ``delete_model`` method is given the ``HttpRequest`` and a model instance. -Use this method to do pre- or post-delete operations. + The ``delete_model`` method is given the ``HttpRequest`` and a model + instance. Use this method to do pre- or post-delete operations. .. 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 + .. 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`:: + 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 + 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:: + .. 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. + 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: + 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. + * 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:: + 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.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) 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 @@ -997,9 +1013,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 @@ -1016,8 +1032,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. @@ -1029,33 +1045,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 ----------------------------- @@ -1085,14 +1102,15 @@ all the same functionality as well as some of its own: through to ``inlineformset_factory`` when creating the formset for this inline. -.. _ref-contrib-admin-inline-extra: + .. _ref-contrib-admin-inline-extra: .. 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 @@ -1103,7 +1121,7 @@ all the same functionality as well as some of its own: 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 @@ -1322,8 +1340,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 ----------------------------------------------- @@ -1331,15 +1349,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 @@ -1409,8 +1427,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 ------------------------ @@ -1425,25 +1444,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 ------------------------ @@ -1453,38 +1472,39 @@ 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. .. versionadded:: 1.3 .. attribute:: AdminSite.login_form -Subclass of :class:`~django.contrib.auth.forms.AuthenticationForm` that will -be used by the admin site login view. + Subclass of :class:`~django.contrib.auth.forms.AuthenticationForm` 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 ------------------------------------------------- @@ -1619,12 +1639,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,)) |
