From 65411d01d448ff0cd4abd14eee14cf60b5f8fc20 Mon Sep 17 00:00:00 2001 From: Nishanth Amuluru Date: Sat, 8 Jan 2011 11:20:57 +0530 Subject: Added buildout stuff and made changes accordingly --HG-- rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => parts/django/Django.egg-info/dependency_links.txt rename : taskapp/models.py => parts/django/django/conf/app_template/models.py rename : taskapp/tests.py => parts/django/django/conf/app_template/tests.py rename : taskapp/views.py => parts/django/django/conf/app_template/views.py rename : taskapp/views.py => parts/django/django/contrib/gis/tests/geo3d/views.py rename : profile/management/__init__.py => parts/django/tests/modeltests/delete/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/files/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/invalid_models/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/m2m_signals/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/model_package/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/commands/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/models.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/delete_regress/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/file_storage/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/max_lengths/__init__.py rename : profile/forms.py => pytask/profile/forms.py rename : profile/management/__init__.py => pytask/profile/management/__init__.py rename : profile/management/commands/seed_db.py => pytask/profile/management/commands/seed_db.py rename : profile/models.py => pytask/profile/models.py rename : profile/templatetags/user_tags.py => pytask/profile/templatetags/user_tags.py rename : taskapp/tests.py => pytask/profile/tests.py rename : profile/urls.py => pytask/profile/urls.py rename : profile/utils.py => pytask/profile/utils.py rename : profile/views.py => pytask/profile/views.py rename : static/css/base.css => pytask/static/css/base.css rename : taskapp/tests.py => pytask/taskapp/tests.py rename : taskapp/views.py => pytask/taskapp/views.py rename : templates/base.html => pytask/templates/base.html rename : templates/profile/browse_notifications.html => pytask/templates/profile/browse_notifications.html rename : templates/profile/edit.html => pytask/templates/profile/edit.html rename : templates/profile/view.html => pytask/templates/profile/view.html rename : templates/profile/view_notification.html => pytask/templates/profile/view_notification.html rename : templates/registration/activate.html => pytask/templates/registration/activate.html rename : templates/registration/activation_email.txt => pytask/templates/registration/activation_email.txt rename : templates/registration/activation_email_subject.txt => pytask/templates/registration/activation_email_subject.txt rename : templates/registration/logged_out.html => pytask/templates/registration/logged_out.html rename : templates/registration/login.html => pytask/templates/registration/login.html rename : templates/registration/logout.html => pytask/templates/registration/logout.html rename : templates/registration/password_change_done.html => pytask/templates/registration/password_change_done.html rename : templates/registration/password_change_form.html => pytask/templates/registration/password_change_form.html rename : templates/registration/password_reset_complete.html => pytask/templates/registration/password_reset_complete.html rename : templates/registration/password_reset_confirm.html => pytask/templates/registration/password_reset_confirm.html rename : templates/registration/password_reset_done.html => pytask/templates/registration/password_reset_done.html rename : templates/registration/password_reset_email.html => pytask/templates/registration/password_reset_email.html rename : templates/registration/password_reset_form.html => pytask/templates/registration/password_reset_form.html rename : templates/registration/registration_complete.html => pytask/templates/registration/registration_complete.html rename : templates/registration/registration_form.html => pytask/templates/registration/registration_form.html rename : utils.py => pytask/utils.py --- .../ref/contrib/admin/_images/article_actions.png | Bin 0 -> 38545 bytes .../admin/_images/article_actions_message.png | Bin 0 -> 22098 bytes .../ref/contrib/admin/_images/flatfiles_admin.png | Bin 0 -> 42243 bytes .../ref/contrib/admin/_images/user_actions.png | Bin 0 -> 27047 bytes .../ref/contrib/admin/_images/users_changelist.png | Bin 0 -> 59355 bytes parts/django/docs/ref/contrib/admin/actions.txt | 351 +++++ parts/django/docs/ref/contrib/admin/admindocs.txt | 161 ++ parts/django/docs/ref/contrib/admin/index.txt | 1613 ++++++++++++++++++++ 8 files changed, 2125 insertions(+) create mode 100644 parts/django/docs/ref/contrib/admin/_images/article_actions.png create mode 100644 parts/django/docs/ref/contrib/admin/_images/article_actions_message.png create mode 100644 parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png create mode 100644 parts/django/docs/ref/contrib/admin/_images/user_actions.png create mode 100644 parts/django/docs/ref/contrib/admin/_images/users_changelist.png create mode 100644 parts/django/docs/ref/contrib/admin/actions.txt create mode 100644 parts/django/docs/ref/contrib/admin/admindocs.txt create mode 100644 parts/django/docs/ref/contrib/admin/index.txt (limited to 'parts/django/docs/ref/contrib/admin') diff --git a/parts/django/docs/ref/contrib/admin/_images/article_actions.png b/parts/django/docs/ref/contrib/admin/_images/article_actions.png new file mode 100644 index 0000000..78a78ae Binary files /dev/null and b/parts/django/docs/ref/contrib/admin/_images/article_actions.png differ diff --git a/parts/django/docs/ref/contrib/admin/_images/article_actions_message.png b/parts/django/docs/ref/contrib/admin/_images/article_actions_message.png new file mode 100644 index 0000000..6ea9439 Binary files /dev/null and b/parts/django/docs/ref/contrib/admin/_images/article_actions_message.png differ diff --git a/parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png b/parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png new file mode 100644 index 0000000..391a629 Binary files /dev/null and b/parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png differ diff --git a/parts/django/docs/ref/contrib/admin/_images/user_actions.png b/parts/django/docs/ref/contrib/admin/_images/user_actions.png new file mode 100644 index 0000000..fdbe2ad Binary files /dev/null and b/parts/django/docs/ref/contrib/admin/_images/user_actions.png differ diff --git a/parts/django/docs/ref/contrib/admin/_images/users_changelist.png b/parts/django/docs/ref/contrib/admin/_images/users_changelist.png new file mode 100644 index 0000000..d5f9c01 Binary files /dev/null and b/parts/django/docs/ref/contrib/admin/_images/users_changelist.png differ diff --git a/parts/django/docs/ref/contrib/admin/actions.txt b/parts/django/docs/ref/contrib/admin/actions.txt new file mode 100644 index 0000000..0fab59e --- /dev/null +++ b/parts/django/docs/ref/contrib/admin/actions.txt @@ -0,0 +1,351 @@ +============= +Admin actions +============= + +.. versionadded:: 1.1 + +.. currentmodule:: django.contrib.admin + +The basic workflow of Django's admin is, in a nutshell, "select an object, +then change it." This works well for a majority of use cases. However, if you +need to make the same change to many objects at once, this workflow can be +quite tedious. + +In these cases, Django's admin lets you write and register "actions" -- simple +functions that get called with a list of objects selected on the change list +page. + +If you look at any change list in the admin, you'll see this feature in +action; Django ships with a "delete selected objects" action available to all +models. For example, here's the user module from Django's built-in +:mod:`django.contrib.auth` app: + +.. image:: _images/user_actions.png + +.. warning:: + + The "delete selected objects" action uses :meth:`QuerySet.delete() + ` for efficiency reasons, which has an + important caveat: your model's ``delete()`` method will not be called. + + If you wish to override this behavior, simply write a custom action which + accomplishes deletion in your preferred manner -- for example, by calling + ``Model.delete()`` for each of the selected items. + + For more background on bulk deletion, see the documentation on :ref:`object + deletion `. + +Read on to find out how to add your own actions to this list. + +Writing actions +=============== + +The easiest way to explain actions is by example, so let's dive in. + +A common use case for admin actions is the bulk updating of a model. Imagine a +simple news application with an ``Article`` model:: + + from django.db import models + + STATUS_CHOICES = ( + ('d', 'Draft'), + ('p', 'Published'), + ('w', 'Withdrawn'), + ) + + class Article(models.Model): + title = models.CharField(max_length=100) + body = models.TextField() + status = models.CharField(max_length=1, choices=STATUS_CHOICES) + + def __unicode__(self): + return self.title + +A common task we might perform with a model like this is to update an +article's status from "draft" to "published". We could easily do this in the +admin one article at a time, but if we wanted to bulk-publish a group of +articles, it'd be tedious. So, let's write an action that lets us change an +article's status to "published." + +Writing action functions +------------------------ + +First, we'll need to write a function that gets called when the action is +trigged from the admin. Action functions are just regular functions that take +three arguments: + + * The current :class:`ModelAdmin` + * An :class:`~django.http.HttpRequest` representing the current request, + * A :class:`~django.db.models.QuerySet` containing the set of objects + selected by the user. + +Our publish-these-articles function won't need the :class:`ModelAdmin` or the +request object, but we will use the queryset:: + + def make_published(modeladmin, request, queryset): + queryset.update(status='p') + +.. note:: + + For the best performance, we're using the queryset's :ref:`update method + `. Other types of actions might need to deal + with each object individually; in these cases we'd just iterate over the + queryset:: + + for obj in queryset: + do_something_with(obj) + +That's actually all there is to writing an action! However, we'll take one +more optional-but-useful step and give the action a "nice" title in the admin. +By default, this action would appear in the action list as "Make published" -- +the function name, with underscores replaced by spaces. That's fine, but we +can provide a better, more human-friendly name by giving the +``make_published`` function a ``short_description`` attribute:: + + def make_published(modeladmin, request, queryset): + queryset.update(status='p') + make_published.short_description = "Mark selected stories as published" + +.. note:: + + This might look familiar; the admin's ``list_display`` option uses the + same technique to provide human-readable descriptions for callback + functions registered there, too. + +Adding actions to the :class:`ModelAdmin` +----------------------------------------- + +Next, we'll need to inform our :class:`ModelAdmin` of the action. This works +just like any other configuration option. So, the complete ``admin.py`` with +the action and its registration would look like:: + + from django.contrib import admin + from myapp.models import Article + + def make_published(modeladmin, request, queryset): + queryset.update(status='p') + make_published.short_description = "Mark selected stories as published" + + class ArticleAdmin(admin.ModelAdmin): + list_display = ['title', 'status'] + ordering = ['title'] + actions = [make_published] + + admin.site.register(Article, ArticleAdmin) + +That code will give us an admin change list that looks something like this: + +.. image:: _images/article_actions.png + +That's really all there is to it! If you're itching to write your own actions, +you now know enough to get started. The rest of this document just covers more +advanced techniques. + +Advanced action techniques +========================== + +There's a couple of extra options and possibilities you can exploit for more +advanced options. + +Actions as :class:`ModelAdmin` methods +-------------------------------------- + +The example above shows the ``make_published`` action defined as a simple +function. That's perfectly fine, but it's not perfect from a code design point +of view: since the action is tightly coupled to the ``Article`` object, it +makes sense to hook the action to the ``ArticleAdmin`` object itself. + +That's easy enough to do:: + + class ArticleAdmin(admin.ModelAdmin): + ... + + actions = ['make_published'] + + def make_published(self, request, queryset): + queryset.update(status='p') + make_published.short_description = "Mark selected stories as published" + +Notice first that we've moved ``make_published`` into a method and renamed the +`modeladmin` parameter to `self`, and second that we've now put the string +``'make_published'`` in ``actions`` instead of a direct function reference. This +tells the :class:`ModelAdmin` to look up the action as a method. + +Defining actions as methods gives the action more straightforward, idiomatic +access to the :class:`ModelAdmin` itself, allowing the action to call any of the +methods provided by the admin. + +.. _custom-admin-action: + +For example, we can use ``self`` to flash a message to the user informing her +that the action was successful:: + + class ArticleAdmin(admin.ModelAdmin): + ... + + def make_published(self, request, queryset): + rows_updated = queryset.update(status='p') + if rows_updated == 1: + message_bit = "1 story was" + else: + message_bit = "%s stories were" % rows_updated + self.message_user(request, "%s successfully marked as published." % message_bit) + +This make the action match what the admin itself does after successfully +performing an action: + +.. image:: _images/article_actions_message.png + +Actions that provide intermediate pages +--------------------------------------- + +By default, after an action is performed the user is simply redirected back +to the original change list page. However, some actions, especially more +complex ones, will need to return intermediate pages. For example, the +built-in delete action asks for confirmation before deleting the selected +objects. + +To provide an intermediary page, simply return an +:class:`~django.http.HttpResponse` (or subclass) from your action. For +example, you might write a simple export function that uses Django's +:doc:`serialization functions ` to dump some selected +objects as JSON:: + + from django.http import HttpResponse + from django.core import serializers + + def export_as_json(modeladmin, request, queryset): + response = HttpResponse(mimetype="text/javascript") + serializers.serialize("json", queryset, stream=response) + return response + +Generally, something like the above isn't considered a great idea. Most of the +time, the best practice will be to return an +:class:`~django.http.HttpResponseRedirect` and redirect the user to a view +you've written, passing the list of selected objects in the GET query string. +This allows you to provide complex interaction logic on the intermediary +pages. For example, if you wanted to provide a more complete export function, +you'd want to let the user choose a format, and possibly a list of fields to +include in the export. The best thing to do would be to write a small action +that simply redirects to your custom export view:: + + from django.contrib import admin + from django.contrib.contenttypes.models import ContentType + from django.http import HttpResponseRedirect + + def export_selected_objects(modeladmin, request, queryset): + selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME) + ct = ContentType.objects.get_for_model(queryset.model) + return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected))) + +As you can see, the action is the simple part; all the complex logic would +belong in your export view. This would need to deal with objects of any type, +hence the business with the ``ContentType``. + +Writing this view is left as an exercise to the reader. + +.. _adminsite-actions: + +Making actions available site-wide +---------------------------------- + +.. method:: AdminSite.add_action(action[, name]) + + Some actions are best if they're made available to *any* object in the admin + site -- the export action defined above would be a good candidate. You can + make an action globally available using :meth:`AdminSite.add_action()`. For + example:: + + from django.contrib import admin + + admin.site.add_action(export_selected_objects) + + This makes the `export_selected_objects` action globally available as an + action named `"export_selected_objects"`. You can explicitly give the action + a name -- good if you later want to programatically :ref:`remove the action + ` -- by passing a second argument to + :meth:`AdminSite.add_action()`:: + + admin.site.add_action(export_selected_objects, 'export_selected') + +.. _disabling-admin-actions: + +Disabling actions +----------------- + +Sometimes you need to disable certain actions -- especially those +:ref:`registered site-wide ` -- for particular objects. +There's a few ways you can disable actions: + +Disabling a site-wide action +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. method:: AdminSite.disable_action(name) + + If you need to disable a :ref:`site-wide action ` you can + call :meth:`AdminSite.disable_action()`. + + For example, you can use this method to remove the built-in "delete selected + objects" action:: + + admin.site.disable_action('delete_selected') + + Once you've done the above, that action will no longer be available + site-wide. + + If, however, you need to re-enable a globally-disabled action for one + particular model, simply list it explicitly in your ``ModelAdmin.actions`` + list:: + + # Globally disable delete selected + admin.site.disable_action('delete_selected') + + # This ModelAdmin will not have delete_selected available + class SomeModelAdmin(admin.ModelAdmin): + actions = ['some_other_action'] + ... + + # This one will + class AnotherModelAdmin(admin.ModelAdmin): + actions = ['delete_selected', 'a_third_action'] + ... + + +Disabling all actions for a particular :class:`ModelAdmin` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want *no* bulk actions available for a given :class:`ModelAdmin`, simply +set :attr:`ModelAdmin.actions` to ``None``:: + + class MyModelAdmin(admin.ModelAdmin): + actions = None + +This tells the :class:`ModelAdmin` to not display or allow any actions, +including any :ref:`site-wide actions `. + +Conditionally enabling or disabling actions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. method:: ModelAdmin.get_actions(request) + + Finally, you can conditionally enable or disable actions on a per-request + (and hence per-user basis) by overriding :meth:`ModelAdmin.get_actions`. + + This returns a dictionary of actions allowed. The keys are action names, and + the values are ``(function, name, short_description)`` tuples. + + Most of the time you'll use this method to conditionally remove actions from + the list gathered by the superclass. For example, if I only wanted users + whose names begin with 'J' to be able to delete objects in bulk, I could do + the following:: + + class MyModelAdmin(admin.ModelAdmin): + ... + + def get_actions(self, request): + actions = super(MyModelAdmin, self).get_actions(request) + if request.user.username[0].upper() != 'J': + del actions['delete_selected'] + return actions + + diff --git a/parts/django/docs/ref/contrib/admin/admindocs.txt b/parts/django/docs/ref/contrib/admin/admindocs.txt new file mode 100644 index 0000000..6743921 --- /dev/null +++ b/parts/django/docs/ref/contrib/admin/admindocs.txt @@ -0,0 +1,161 @@ +======================================== +The Django admin documentation generator +======================================== + +.. module:: django.contrib.admindocs + :synopsis: Django's admin documentation generator. + +.. currentmodule:: django.contrib.admindocs + +Django's :mod:`~django.contrib.admindocs` app pulls documentation from the +docstrings of models, views, template tags, and template filters for any app in +:setting:`INSTALLED_APPS` and makes that documentation available from the +:mod:`Django admin `. + +In addition to providing offline documentation for all template tags and +template filters that ship with Django, you may utilize admindocs to quickly +document your own code. + +Overview +======== + +To activate the :mod:`~django.contrib.admindocs`, you will need to do +the following: + + * Add :mod:`django.contrib.admindocs` to your :setting:`INSTALLED_APPS`. + * Add ``(r'^admin/doc/', include('django.contrib.admindocs.urls'))`` to + your :data:`urlpatterns`. Make sure it's included *before* the + ``r'^admin/'`` entry, so that requests to ``/admin/doc/`` don't get + handled by the latter entry. + * Install the docutils Python module (http://docutils.sf.net/). + * **Optional:** Linking to templates requires the :setting:`ADMIN_FOR` + setting to be configured. + * **Optional:** Using the admindocs bookmarklets requires the + :mod:`XViewMiddleware` to be installed. + +Once those steps are complete, you can start browsing the documentation by +going to your admin interface and clicking the "Documentation" link in the +upper right of the page. + +Documentation helpers +===================== + +The following special markup can be used in your docstrings to easily create +hyperlinks to other components: + +================= ======================= +Django Component reStructuredText roles +================= ======================= +Models ``:model:`appname.ModelName``` +Views ``:view:`appname.view_name``` +Template tags ``:tag:`tagname``` +Template filters ``:filter:`filtername``` +Templates ``:template:`path/to/template.html``` +================= ======================= + +Model reference +=============== + +The **models** section of the ``admindocs`` page describes each model in the +system along with all the fields and methods available on it. Relationships to +other models appear as hyperlinks. Descriptions are pulled from ``help_text`` +attributes on fields or from docstrings on model methods. + +A model with useful documentation might look like this:: + + class BlogEntry(models.Model): + """ + Stores a single blog entry, related to :model:`blog.Blog` and + :model:`auth.User`. + + """ + slug = models.SlugField(help_text="A short label, generally used in URLs.") + author = models.ForeignKey(User) + blog = models.ForeignKey(Blog) + ... + + def publish(self): + """Makes the blog entry live on the site.""" + ... + +View reference +============== + +Each URL in your site has a separate entry in the ``admindocs`` page, and +clicking on a given URL will show you the corresponding view. Helpful things +you can document in your view function docstrings include: + + * A short description of what the view does. + * The **context**, or a list of variables available in the view's template. + * The name of the template or templates that are used for that view. + +For example:: + + from myapp.models import MyModel + + def my_view(request, slug): + """ + Display an individual :model:`myapp.MyModel`. + + **Context** + + ``RequestContext`` + + ``mymodel`` + An instance of :model:`myapp.MyModel`. + + **Template:** + + :template:`myapp/my_template.html` + + """ + return render_to_response('myapp/my_template.html', { + 'mymodel': MyModel.objects.get(slug=slug) + }, context_instance=RequestContext(request)) + + +Template tags and filters reference +=================================== + +The **tags** and **filters** ``admindocs`` sections describe all the tags and +filters that come with Django (in fact, the :ref:`built-in tag reference +` and :ref:`built-in filter reference +` documentation come directly from those +pages). Any tags or filters that you create or are added by a third-party app +will show up in these sections as well. + + +Template reference +================== + +While ``admindocs`` does not include a place to document templates by +themselves, if you use the ``:template:`path/to/template.html``` syntax in a +docstring the resulting page will verify the path of that template with +Django's :ref:`template loaders `. This can be a handy way to +check if the specified template exists and to show where on the filesystem that +template is stored. + + +Included Bookmarklets +===================== + +Several useful bookmarklets are available from the ``admindocs`` page: + + Documentation for this page + Jumps you from any page to the documentation for the view that generates + that page. + + Show object ID + Shows the content-type and unique ID for pages that represent a single + object. + + Edit this object + Jumps to the admin page for pages that represent a single object. + +Using these bookmarklets requires that you are either logged into the +:mod:`Django admin ` as a +:class:`~django.contrib.auth.models.User` with +:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or +that the :mod:`django.middleware.doc` middleware and +:mod:`XViewMiddleware ` are installed and you +are accessing the site from an IP address listed in :setting:`INTERNAL_IPS`. diff --git a/parts/django/docs/ref/contrib/admin/index.txt b/parts/django/docs/ref/contrib/admin/index.txt new file mode 100644 index 0000000..b99cfdc --- /dev/null +++ b/parts/django/docs/ref/contrib/admin/index.txt @@ -0,0 +1,1613 @@ +===================== +The Django admin site +===================== + +.. module:: django.contrib.admin + :synopsis: Django's 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 six steps in activating the Django admin site: + + 1. Add ``'django.contrib.admin'`` to your :setting:`INSTALLED_APPS` + setting. + + 2. Admin has two dependencies - ``django.contrib.auth`` and + ``django.contrib.contenttypes``. If these applications are not + in your :setting:`INSTALLED_APPS` list, add them. + + 3. Determine which of your application's models should be editable in the + admin interface. + + 4. For each of those models, optionally create a ``ModelAdmin`` class that + encapsulates the customized admin functionality and options for that + particular model. + + 5. Instantiate an ``AdminSite`` and tell it about each of your models and + ``ModelAdmin`` classes. + + 6. Hook the ``AdminSite`` instance into your URLconf. + +Other topics +------------ + +.. toctree:: + :maxdepth: 1 + + actions + admindocs + +.. seealso:: + + For information about serving the media files (images, JavaScript, and CSS) + associated with the admin in production, see :ref:`serving-media-files`. + +``ModelAdmin`` objects +====================== + +.. 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``:: + + from django.contrib import admin + from myproject.myapp.models import Author + + class AuthorAdmin(admin.ModelAdmin): + pass + admin.site.register(Author, AuthorAdmin) + +.. 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:: + + from django.contrib import admin + from myproject.myapp.models import Author + + admin.site.register(Author) + +``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' + +.. 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. + +Example:: + + 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. + +For an example see the section `Adding custom validation to the admin`_. + +.. attribute:: ModelAdmin.fieldsets + +Set ``fieldsets`` to control the layout of admin "add" and "change" pages. + +``fieldsets`` is a list of two-tuples, in which each two-tuple represents a +``
`` on the admin form page. (A ``
`` 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:: _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. + +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'), + } + + .. versionadded:: 1.2 + + ``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. + + 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. + + 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:: + + 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. + +.. versionadded:: 1.2 + +``fields`` can contain values defined in :attr:`ModelAdmin.readonly_fields` +to be displayed as read-only. + +.. 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. + +.. attribute:: ModelAdmin.exclude + +This attribute, if given, should be a list of field names to exclude from the +form. + +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) + +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): + 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. + +.. attribute:: ModelAdmin.filter_horizontal + +Use a nifty unobtrusive JavaScript "filter" interface instead of the +usability-challenged ``) 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. + +.. attribute:: ModelAdmin.raw_id_fields + +By default, Django's admin uses a select-box interface (