diff options
Diffstat (limited to 'docs/admin.txt')
| -rw-r--r-- | docs/admin.txt | 678 |
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), + ) |
