summaryrefslogtreecommitdiff
path: root/docs/admin.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/admin.txt')
-rw-r--r--docs/admin.txt678
1 files changed, 678 insertions, 0 deletions
diff --git a/docs/admin.txt b/docs/admin.txt
new file mode 100644
index 0000000000..fbdd19bc90
--- /dev/null
+++ b/docs/admin.txt
@@ -0,0 +1,678 @@
+=====================
+The Django admin site
+=====================
+
+One of the most powerful parts of Django is the automatic admin interface. It
+reads metadata in your model to provide a powerful and production-ready
+interface that content producers can immediately use to start adding content to
+the site. In this document, we discuss how to activate, use and customize
+Django's admin interface.
+
+.. admonition:: Note
+
+ The admin site has been refactored significantly since Django 0.96. This
+ document describes the newest version of the admin site, which allows for
+ much richer customization. If you follow the development of Django itself,
+ you may have heard this described as "newforms-admin."
+
+Overview
+========
+
+There are four steps in activating the Django admin site:
+
+ 1. Determine which of your application's models should be editable in the
+ admin interface.
+
+ 2. For each of those models, optionally create a ``ModelAdmin`` class that
+ encapsulates the customized admin functionality and options for that
+ particular model.
+
+ 3. Instantiate an ``AdminSite`` and tell it about each of your models and
+ ``ModelAdmin`` classes.
+
+ 4. Hook the ``AdminSite`` instance into your URLconf.
+
+``ModelAdmin`` objects
+======================
+
+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 the ``ModelAdmin``::
+
+ from django.contrib import admin
+ from myproject.myapp.models import Author
+
+ class AuthorAdmin(admin.ModelAdmin):
+ pass
+ admin.site.register(Author, AuthorAdmin)
+
+``ModelAdmin`` Options
+----------------------
+
+The ``ModelAdmin`` is very flexible. It has several options for dealing with
+customizing the interface. All options are defined on the ``ModelAdmin``
+subclass::
+
+ class AuthorAdmin(admin.ModelAdmin):
+ date_hierarchy = 'pub_date'
+
+``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.
+
+Example::
+
+ date_hierarchy = 'pub_date'
+
+``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')
+ }),
+ )
+
+This results in an admin page that looks like:
+
+ .. image:: http://media.djangoproject.com/img/doc/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.
+
+The ``field_options`` dictionary can have the following keys:
+
+``fields``
+ A tuple of field names to display in this fieldset. This key is required.
+
+ Example::
+
+ {
+ '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::
+
+ {
+ 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
+ }
+
+``classes``
+ A string containing extra CSS classes to apply to the fieldset.
+
+ Example::
+
+ {
+ 'classes': 'wide',
+ }
+
+ Apply multiple classes by separating them with spaces. Example::
+
+ {
+ '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.
+
+``description``
+ A string of optional extra text to be displayed at the top of each fieldset,
+ under the heading of the fieldset. It's used verbatim, so you can use any HTML
+ and you must escape any special HTML characters (such as ampersands) yourself.
+
+``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.
+
+``filter_vertical``
+~~~~~~~~~~~~~~~~~~~
+
+Same as ``filter_horizontal``, but is a vertical display of the filter
+interface.
+
+``list_display``
+~~~~~~~~~~~~~~~~
+
+Set ``list_display`` to control which fields are displayed on the change list
+page of the admin.
+
+Example::
+
+ 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.
+
+A few special cases to note about ``list_display``:
+
+ * 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``.)
+
+ * 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, Django will call it and
+ display the output. This method should have a ``short_description``
+ function attribute, for use as the header for the field.
+
+ Here's a full example model::
+
+ 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'
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('name', 'decade_born_in')
+
+ * If the string given is a method of the model, 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::
+
+ 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
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'last_name', 'colored_name')
+
+ * If the string given is a method of the model 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::
+
+ 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] == 5
+ born_in_fifties.boolean = True
+
+ 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::
+
+ 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).
+
+ 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::
+
+ 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'
+
+ 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.
+
+``list_display_links``
+~~~~~~~~~~~~~~~~~~~~~~
+
+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.
+
+``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::
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('first_name', 'last_name', 'birthday')
+ list_display_links = ('first_name', 'last_name')
+
+Finally, note that in order to use ``list_display_links``, you must define
+``list_display``, too.
+
+``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``.
+
+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')
+
+The above code results in an admin change list page that looks like this:
+
+ .. image:: http://media.djangoproject.com/img/doc/users_changelist.png
+
+(This example also has ``search_fields`` defined. See below.)
+
+``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``.
+
+``list_select_related``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Set ``list_select_related`` to tell Django to use ``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``.
+
+Note that Django will use ``select_related()``, regardless of this setting,
+if one of the ``list_display`` fields is a ``ForeignKey``.
+
+For more on ``select_related()``, see `the select_related() docs`_.
+
+.. _the select_related() docs: ../db-api/#select-related
+
+``inlines``
+~~~~~~~~~~~
+
+See ``InlineModelAdmin`` objects below.
+
+``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.
+
+If this isn't provided, the Django admin will use the model's default ordering.
+
+``prepopulated_fields``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Set ``prepopulated_fields`` to a dictionary mapping field names to the fields
+it should prepopulate from::
+
+ 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.
+
+``prepopulated_fields`` doesn't accept DateTimeFields, ForeignKeys nor
+ManyToManyFields.
+
+``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::
+
+ class PersonAdmin(admin.ModelAdmin):
+ radio_fields = {"group": admin.VERTICAL}
+
+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.
+
+``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.
+
+``raw_id_fields`` is a list of fields you would like to change
+into a ``Input`` widget for the primary key.
+
+``save_as``
+~~~~~~~~~~~
+
+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.
+
+"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``.
+
+``save_on_top``
+~~~~~~~~~~~~~~~
+
+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.
+
+By default, ``save_on_top`` is set to ``False``.
+
+``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.
+
+These fields should be some kind of text field, such as ``CharField`` or
+``TextField``. You can also perform a related lookup on a ``ForeignKey`` with
+the lookup API "follow" notation::
+
+ search_fields = ['foreign_key__related_fieldname']
+
+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%')
+
+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::
+
+ 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.
+
+``=``
+ 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')
+
+ 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.
+
+``ModelAdmin`` media definitions
+--------------------------------
+
+There are times where you would like add a bit of CSS and/or Javascript to
+the add/change views. This can be accomplished by using a Media inner class
+on your ``ModelAdmin``::
+
+ class ArticleAdmin(admin.ModelAdmin):
+ class Media:
+ css = {
+ "all": ("my_styles.css",)
+ }
+ js = ("my_code.js",)
+
+Keep in mind that this will be prepended with ``MEDIA_URL``. The same rules
+apply as `regular media definitions on forms`_.
+
+.. _regular media definitions on forms: ../newforms/#media
+
+``InlineModelAdmin`` objects
+============================
+
+The admin interface has the ability to edit models on the same page as a
+parent model. These are called inlines. You can add them a model being
+specifing them in a ``ModelAdmin.inlines`` attribute::
+
+ class BookInline(admin.TabularInline):
+ model = Book
+
+ class AuthorAdmin(admin.ModelAdmin):
+ inlines = [
+ BookInline,
+ ]
+
+Django provides two subclasses of ``InlineModelAdmin`` and they are::
+
+ * ``TabularInline``
+ * ``StackedInline``
+
+The difference between these two is merely the template used to render them.
+
+``InlineModelAdmin`` options
+-----------------------------
+
+The ``InlineModelAdmin`` class is a subclass of ``ModelAdmin`` so it inherits
+all the same functionality as well as some of its own:
+
+``model``
+~~~~~~~~~
+
+The model in which the inline is using. This is required.
+
+``fk_name``
+~~~~~~~~~~~
+
+The name of the foreign key on the model. In most cases this will be dealt
+with automatically, but ``fk_name`` must be specified explicitly if there are
+more than one foreign key to the same parent model.
+
+``formset``
+~~~~~~~~~~~
+
+This defaults to ``BaseInlineFormset``. Using your own formset can give you
+many possibilities of customization. Inlines are built around
+`model formsets`_.
+
+.. _model formsets: ../modelforms/#model-formsets
+
+``form``
+~~~~~~~~
+
+The value for ``form`` is inherited from ``ModelAdmin``. This is what is
+passed through to ``formset_factory`` when creating the formset for this
+inline.
+
+``extra``
+~~~~~~~~~
+
+This controls the number of extra forms the formset will display in addition
+to the initial forms. See the `formsets documentation`_ for more information.
+
+.. _formsets documentation: ../newforms/#formsets
+
+``max_num``
+~~~~~~~~~~~
+
+This controls the maximum number of forms to show in the inline. This doesn't
+directly corrolate to the number of objects, but can if the value is small
+enough. See `max_num in formsets`_ for more information.
+
+.. _max_num in formsets: ../modelforms/#limiting-the-number-of-objects-editable
+
+``template``
+~~~~~~~~~~~~
+
+The template used to render the inline on the page.
+
+``verbose_name``
+~~~~~~~~~~~~~~~~
+
+An override to the ``verbose_name`` found in the model's inner ``Meta`` class.
+
+``verbose_name_plural``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+An override to the ``verbose_name_plural`` found in the model's inner ``Meta``
+class.
+
+Working with a model with two or more foreign keys to the same parent model
+---------------------------------------------------------------------------
+
+It is sometimes possible to have more than one foreign key to the same model.
+Take this model for instance::
+
+ class Friendship(models.Model):
+ to_person = models.ForeignKey(Person, related_name="friends")
+ from_person = models.ForeignKey(Person, related_name="from_friends")
+
+If you wanted to display an inline on the ``Person`` admin add/change pages
+you need to explicitly define the foreign key since it is unable to do so
+automatically::
+
+ class FriendshipInline(admin.TabularInline):
+ model = Friendship
+ fk_name = "to_person"
+
+ class PersonAdmin(admin.ModelAdmin):
+ inlines = [
+ FriendshipInline,
+ ]
+
+``AdminSite`` objects
+=====================
+
+Hooking ``AdminSite`` instances into your URLconf
+-------------------------------------------------
+
+The last step in setting up the Django admin is to hook your ``AdminSite``
+instance into your URLconf. Do this by pointing a given URL at the
+``AdminSite.root`` method.
+
+In this example, we register the default ``AdminSite`` instance
+``django.contrib.admin.site`` at the URL ``/admin/`` ::
+
+ # urls.py
+ from django.conf.urls.defaults import *
+ from django.contrib import admin
+
+ admin.autodiscover()
+
+ urlpatterns = patterns('',
+ ('^admin/(.*)', admin.site.root),
+ )
+
+Above we used ``admin.autodiscover()`` to automatically load the
+``INSTALLED_APPS`` admin.py modules.
+
+In this example, we register the ``AdminSite`` instance
+``myproject.admin.admin_site`` at the URL ``/myadmin/`` ::
+
+ # urls.py
+ from django.conf.urls.defaults import *
+ from myproject.admin import admin_site
+
+ urlpatterns = patterns('',
+ ('^myadmin/(.*)', admin_site.root),
+ )
+
+There is really no need to use autodiscover when using your own ``AdminSite``
+instance since you will likely be importing all the per-app admin.py modules
+in your ``myproject.admin`` module.
+
+Note that the regular expression in the URLpattern *must* group everything in
+the URL that comes after the URL root -- hence the ``(.*)`` in these examples.
+
+Multiple admin sites in the same URLconf
+----------------------------------------
+
+It's easy to create multiple instances of the admin site on the same
+Django-powered Web site. Just create multiple instances of ``AdminSite`` and
+root each one at a different URL.
+
+In this example, the URLs ``/basic-admin/`` and ``/advanced-admin/`` feature
+separate versions of the admin site -- using the ``AdminSite`` instances
+``myproject.admin.basic_site`` and ``myproject.admin.advanced_site``,
+respectively::
+
+ # urls.py
+ from django.conf.urls.defaults import *
+ from myproject.admin import basic_site, advanced_site
+
+ urlpatterns = patterns('',
+ ('^basic-admin/(.*)', basic_site.root),
+ ('^advanced-admin/(.*)', advanced_site.root),
+ )