Commits

Samuel Martin committed 8d5e24a

Ajout fichers manquants howto

  • Participants
  • Parent commits 52236d8

Comments (0)

Files changed (11)

File howto/auth-remote-user.txt

+====================================
+Authentication using ``REMOTE_USER``
+====================================
+
+.. currentmodule:: django.contrib.auth.backends
+
+This document describes how to make use of external authentication sources
+(where the Web server sets the ``REMOTE_USER`` environment variable) in your
+Django applications.  This type of authentication solution is typically seen on
+intranet sites, with single sign-on solutions such as IIS and Integrated
+Windows Authentication or Apache and `mod_authnz_ldap`_, `CAS`_, `Cosign`_,
+`WebAuth`_, `mod_auth_sspi`_, etc.
+
+.. _mod_authnz_ldap: http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html
+.. _CAS: http://www.jasig.org/cas
+.. _Cosign: http://weblogin.org
+.. _WebAuth: http://www.stanford.edu/services/webauth/
+.. _mod_auth_sspi: http://sourceforge.net/projects/mod-auth-sspi
+
+When the Web server takes care of authentication it typically sets the
+``REMOTE_USER`` environment variable for use in the underlying application.  In
+Django, ``REMOTE_USER`` is made available in the :attr:`request.META
+<django.http.HttpRequest.META>` attribute.  Django can be configured to make
+use of the ``REMOTE_USER`` value using the ``RemoteUserMiddleware`` and
+``RemoteUserBackend`` classes found in :mod:`django.contrib.auth`.
+
+Configuration
+=============
+
+First, you must add the
+:class:`django.contrib.auth.middleware.RemoteUserMiddleware` to the
+:setting:`MIDDLEWARE_CLASSES` setting **after** the
+:class:`django.contrib.auth.middleware.AuthenticationMiddleware`::
+
+    MIDDLEWARE_CLASSES = (
+        ...
+        'django.contrib.auth.middleware.AuthenticationMiddleware',
+        'django.contrib.auth.middleware.RemoteUserMiddleware',
+        ...
+        )
+
+Next, you must replace the :class:`~django.contrib.auth.backends.ModelBackend`
+with ``RemoteUserBackend`` in the :setting:`AUTHENTICATION_BACKENDS` setting::
+
+    AUTHENTICATION_BACKENDS = (
+        'django.contrib.auth.backends.RemoteUserBackend',
+    )
+
+With this setup, ``RemoteUserMiddleware`` will detect the username in
+``request.META['REMOTE_USER']`` and will authenticate and auto-login that user
+using the ``RemoteUserBackend``.
+
+.. note::
+   Since the ``RemoteUserBackend`` inherits from ``ModelBackend``, you will
+   still have all of the same permissions checking that is implemented in
+   ``ModelBackend``.
+
+If your authentication mechanism uses a custom HTTP header and not
+``REMOTE_USER``, you can subclass ``RemoteUserMiddleware`` and set the
+``header`` attribute to the desired ``request.META`` key.  For example::
+
+    from django.contrib.auth.middleware import RemoteUserMiddleware
+
+    class CustomHeaderMiddleware(RemoteUserMiddleware):
+        header = 'HTTP_AUTHUSER'
+
+
+``RemoteUserBackend``
+=====================
+
+.. class:: django.contrib.auth.backends.RemoteUserBackend
+
+If you need more control, you can create your own authentication backend
+that inherits from ``RemoteUserBackend`` and overrides certain parts:
+
+Attributes
+~~~~~~~~~~
+
+.. attribute:: RemoteUserBackend.create_unknown_user
+
+    ``True`` or ``False``.  Determines whether or not a
+    :class:`~django.contrib.auth.models.User` object is created if not already
+    in the database.  Defaults to ``True``.
+
+Methods
+~~~~~~~
+
+.. method:: RemoteUserBackend.clean_username(username)
+
+   Performs any cleaning on the ``username`` (e.g. stripping LDAP DN
+   information) prior to using it to get or create a
+   :class:`~django.contrib.auth.models.User` object.  Returns the cleaned
+   username.
+
+.. method:: RemoteUserBackend.configure_user(user)
+
+   Configures a newly created user.  This method is called immediately after a
+   new user is created, and can be used to perform custom setup actions, such
+   as setting the user's groups based on attributes in an LDAP directory.
+   Returns the user object.

File howto/contribute.txt

+===========================
+How to contribute to Django
+===========================
+
+Django is developed 100% by the community, and the more people that are actively
+involved in the code the better Django will be. We recognize that contributing
+to Django can be daunting at first and sometimes confusing even to
+veterans. While we have our official "Contributing to Django" documentation
+which spells out the technical details of triaging tickets and submitting
+patches, it leaves a lot of room for interpretation. This guide aims to offer
+more general advice on issues such as how to interpret the various stages and
+flags in Trac, and how new contributors can get started.
+
+.. seealso::
+
+    This guide is meant to answer the most common questions about
+    contributing to Django, however it is no substitute for the
+    :doc:`/internals/contributing` reference. Please make sure to
+    read that document to understand the specific details
+    involved in reporting issues and submitting patches.
+
+.. _the-spirit-of-contributing:
+
+"The Spirit of Contributing"
+============================
+
+Django uses Trac_ for managing our progress, and Trac is a community-tended
+garden of the bugs people have found and the features people would like to see
+added. As in any garden, sometimes there are weeds to be pulled and sometimes
+there are flowers and vegetables that need picking. We need your help to sort
+out one from the other, and in the end we all benefit together.
+
+Like all gardens, we can aspire to perfection but in reality there's no such
+thing. Even in the most pristine garden there are still snails and insects. In a
+community garden there are also helpful people who--with the best of
+intentions--fertilize the weeds and poison the roses. It's the job of the
+community as a whole to self-manage, keep the problems to a minimum, and educate
+those coming into the community so that they can become valuable contributing
+members.
+
+Similarly, while we aim for Trac to be a perfect representation of the state of
+Django's progress, we acknowledge that this simply will not happen. By
+distributing the load of Trac maintenance to the community, we accept that there
+will be mistakes. Trac is "mostly accurate", and we give allowances for the fact
+that sometimes it will be wrong. That's okay. We're perfectionists with
+deadlines.
+
+We rely on the community to keep participating, keep tickets as accurate as
+possible, and raise issues for discussion on our mailing lists when there is
+confusion or disagreement.
+
+Django is a community project, and every contribution helps. We can't do this
+without YOU!
+
+.. _Trac: http://code.djangoproject.com/
+
+Understanding Trac
+==================
+
+Trac is Django's sole official issue tracker. All known bugs, desired features
+and ideas for changes are logged there.
+
+However, Trac can be quite confusing even to veteran contributors.  Having to
+look at both flags and triage stages isn't immediately obvious, and the stages
+themselves can be misinterpreted.
+
+.. _triage-stages-explained:
+
+What Django's triage stages "really mean"
+-----------------------------------------
+
+Unreviewed
+~~~~~~~~~~
+
+The ticket has not been reviewed by anyone who felt qualified to make a judgment
+about whether the ticket contained a valid issue, a viable feature, or ought to
+be closed for any of the various reasons.
+
+Accepted
+~~~~~~~~
+
+The big grey area! The absolute meaning of "accepted" is that the issue
+described in the ticket is valid and is in some stage of being worked on. Beyond
+that there are several considerations
+
+
+* **Accepted + No Flags**
+
+  The ticket is valid, but no one has submitted a patch for it yet. Often this
+  means you could safely start writing a patch for it.
+
+* **Accepted + Has Patch**
+
+  The ticket is waiting for people to review the supplied patch. This means
+  downloading the patch and trying it out, verifying that it contains tests and
+  docs, running the test suite with the included patch, and leaving feedback on
+  the ticket.
+
+
+* **Accepted + Has Patch + (any other flag)**
+
+  This means the ticket has been reviewed, and has been found to need further
+  work. "Needs tests" and "Needs documentation" are self-explanatory. "Patch
+  needs improvement" will generally be accompanied by a comment on the ticket
+  explaining what is needed to improve the code.
+
+Design Decision Needed
+~~~~~~~~~~~~~~~~~~~~~~
+
+This stage is for issues which may be contentious, may be backwards
+incompatible, or otherwise involve high-level design decisions. These decisions
+are generally made by the core committers, however that is not a
+requirement. See the FAQ below for "My ticket has been in DDN forever!  What
+should I do?"
+
+Ready For Checkin
+~~~~~~~~~~~~~~~~~
+
+The ticket was reviewed by any member of the community other than the person who
+supplied the patch and found to meet all the requirements for a commit-ready
+patch. A core committer now needs to give the patch a final review prior to
+being committed. See the FAQ below for "My ticket has been in RFC forever!  What
+should I do?"
+
+Someday/Maybe?
+~~~~~~~~~~~~~~
+
+Generally only used for vague/high-level features or design ideas. These tickets
+are uncommon and overall less useful since they don't describe concrete
+actionable issues.
+
+Fixed on a branch
+~~~~~~~~~~~~~~~~~
+
+Used to indicate that a ticket is resolved as part of a major body of work that
+will eventually be merged to trunk.  Tickets in this stage generally don't need
+further work. This may happen in the case of major features/refactors in each
+release cycle, or as part of the annual Google Summer of Code efforts.
+
+.. _closing-tickets:
+
+Closing Tickets
+---------------
+
+When a ticket has completed its useful lifecycle, it's time for it to be closed.
+Closing a ticket is a big responsibility, though. You have to be sure that
+the issue is really resolved, and you need to keep in mind that the reporter
+of the ticket may not be happy to have their ticket closed (unless it's fixed,
+of course). If you're not certain about closing a ticket, just leave a comment
+with your thoughts instead.
+
+If you do close a ticket, you should always make sure of the following:
+
+  * Be certain that the issue is resolved.
+
+  * Leave a comment explaining the decision to close the ticket.
+
+  * If there is a way they can improve the ticket to reopen it, let them know.
+
+  * If the ticket is a duplicate, reference the original ticket.
+
+  * **Be polite.** No one likes having their ticket closed. It can be
+    frustrating or even discouraging. The best way to avoid turning people
+    off from contributing to Django is to be polite and friendly and to offer
+    suggestions for how they could improve this ticket and other tickets in the
+    future.
+
+.. seealso::
+
+    The :ref:`contributing reference <ticket-resolutions>` contains a
+    description of each of the available resolutions in Trac.
+
+Example Trac workflow
+---------------------
+
+Here we see the life-cycle of an average ticket:
+
+* Alice creates a ticket, and uploads an incomplete patch (no tests, incorrect
+  implementation).
+
+* Bob reviews the patch, marks it "Accepted", "needs tests", and "patch needs
+  improvement", and leaves a comment telling Alice how the patch could be
+  improved.
+
+* Alice updates the patch, adding tests (but not changing the
+  implementation). She removes the two flags.
+
+* Charlie reviews the patch and resets the "patch needs improvement" flag with
+  another comment about improving the implementation.
+
+* Alice updates the patch, fixing the implementation. She removes the "patch
+  needs improvement" flag.
+
+* Daisy reviews the patch, and marks it RFC.
+
+* Jacob reviews the RFC patch, applies it to his checkout, and commits it.
+
+Some tickets require much less feedback than this, but then again some tickets
+require much much more.
+
+Advice for new contributors
+===========================
+
+New contributor and not sure what to do? Want to help but just don't know how to
+get started? This is the section for you.
+
+* **Pick a subject area that you care about, that you are familiar with, or that
+  you want to learn about.**
+
+  You don't already have to be an expert on the area you want to work on; you
+  become an expert through your ongoing contributions to the code.
+
+* **Triage tickets.**
+
+  If a ticket is unreviewed and reports a bug, try and duplicate it.  If you can
+  duplicate it and it seems valid, make a note that you confirmed the bug and
+  accept the ticket. Make sure the ticket is filed under the correct component
+  area. Consider writing a patch that adds a test for the bug's behavior, even
+  if you don't fix the bug itself.
+
+* **Look for tickets that are accepted and review patches to build familiarity
+  with the codebase and the process.**
+
+  Mark the appropriate flags if a patch needs docs or tests. Look through the
+  changes a patch makes, and keep an eye out for syntax that is incompatible
+  with older but still supported versions of Python. Run the tests and make sure
+  they pass on your system.  Where possible and relevant, try them out on a
+  database other than SQLite. Leave comments and feedback!
+
+* **Keep old patches up to date.**
+
+  Oftentimes the codebase will change between a patch being submitted and the
+  time it gets reviewed. Make sure it still applies cleanly and functions as
+  expected. Simply updating a patch is both useful and important!
+
+* **Trac isn't an absolute; the context is just as important as the words.**
+
+  When reading Trac, you need to take into account who says things, and when
+  they were said. Support for an idea two years ago doesn't necessarily mean
+  that the idea will still have support. You also need to pay attention to who
+  *hasn't* spoken -- for example, if a core team member hasn't been recently
+  involved in a discussion, then a ticket may not have the support required to
+  get into trunk.
+
+* **Start small.**
+
+  It's easier to get feedback on a little issue than on a big one.
+
+* **If you're going to engage in a big task, make sure that your idea has
+  support first.**
+
+  This means getting someone else to confirm that a bug is real before you fix
+  the issue, and ensuring that the core team supports a proposed feature before
+  you go implementing it.
+
+* **Be bold! Leave feedback!**
+
+  Sometimes it can be scary to put your opinion out to the world and say "this
+  ticket is correct" or "this patch needs work", but it's the only way the
+  project moves forward. The contributions of the broad Django community
+  ultimately have a much greater impact than that of the core developers. We
+  can't do it without YOU!
+
+* **Err on the side of caution when marking things Ready For Check-in.**
+
+  If you're really not certain if a ticket is ready, don't mark it as
+  such. Leave a comment instead, letting others know your thoughts.  If you're
+  mostly certain, but not completely certain, you might also try asking on IRC
+  to see if someone else can confirm your suspicions.
+
+* **Wait for feedback, and respond to feedback that you receive.**
+
+  Focus on one or two tickets, see them through from start to finish, and
+  repeat. The shotgun approach of taking on lots of tickets and letting some
+  fall by the wayside ends up doing more harm than good.
+
+* **Be rigorous.**
+
+  When we say ":pep:`8`, and must have docs and tests", we mean it. If a patch
+  doesn't have docs and tests, there had better be a good reason. Arguments like
+  "I couldn't find any existing tests of this feature" don't carry much
+  weight--while it may be true, that means you have the extra-important job of
+  writing the very first tests for that feature, not that you get a pass from
+  writing tests altogether.
+
+.. note::
+
+    The `Reports page`_ contains links to many useful Trac queries, including
+    several that are useful for triaging tickets and reviewing patches as
+    suggested above.
+
+    .. _Reports page: http://code.djangoproject.com/wiki/Reports
+
+
+FAQs
+====
+
+**This ticket I care about has been ignored for days/weeks/months! What can I do
+to get it committed?**
+
+* First off, it's not personal. Django is entirely developed by volunteers (even
+  the core devs), and sometimes folks just don't have time. The best thing to do
+  is to send a gentle reminder to the Django Developers mailing list asking for
+  review on the ticket, or to bring it up in the #django-dev IRC channel.
+
+
+**I'm sure my ticket is absolutely 100% perfect, can I mark it as RFC myself?**
+
+* Short answer: No. It's always better to get another set of eyes on a
+  ticket. If you're having trouble getting that second set of eyes, see question
+  1, above.
+
+
+**My ticket has been in DDN forever! What should I do?**
+
+* Design Decision Needed requires consensus about the right solution.  At the
+  very least it needs consensus among the core developers, and ideally it has
+  consensus from the community as well. The best way to accomplish this is to
+  start a thread on the Django Developers mailing list, and for very complex
+  issues to start a wiki page summarizing the problem and the possible
+  solutions.

File howto/custom-management-commands.txt

+====================================
+Writing custom django-admin commands
+====================================
+
+Applications can register their own actions with ``manage.py``. For example,
+you might want to add a ``manage.py`` action for a Django app that you're
+distributing. In this document, we will be building a custom ``closepoll``
+command for the ``polls`` application from the
+:doc:`tutorial</intro/tutorial01>`.
+
+To do this, just add a ``management/commands`` directory to the application.
+Each Python module in that directory will be auto-discovered and registered as
+a command that can be executed as an action when you run ``manage.py``::
+
+    polls/
+        __init__.py
+        models.py
+        management/
+            __init__.py
+            commands/
+                __init__.py
+                closepoll.py
+        tests.py
+        views.py
+
+In this example, the ``closepoll`` command will be made available to any project
+that includes the ``polls`` application in :setting:`INSTALLED_APPS`.
+
+The ``closepoll.py`` module has only one requirement -- it must define a class
+``Command`` that extends :class:`BaseCommand` or one of its
+:ref:`subclasses<ref-basecommand-subclasses>`.
+
+.. admonition:: Standalone scripts
+
+  Custom management commands are especially useful for running standalone
+  scripts or for scripts that are periodically executed from the UNIX crontab
+  or from Windows scheduled tasks control panel.
+
+To implement the command, edit ``polls/management/commands/closepoll.py`` to
+look like this:
+
+.. code-block:: python
+
+    from django.core.management.base import BaseCommand, CommandError
+    from example.polls.models import Poll
+
+    class Command(BaseCommand):
+        args = '<poll_id poll_id ...>'
+        help = 'Closes the specified poll for voting'
+
+        def handle(self, *args, **options):
+            for poll_id in args:
+                try:
+                    poll = Poll.objects.get(pk=int(poll_id))
+                except Poll.DoesNotExist:
+                    raise CommandError('Poll "%s" does not exist' % poll_id)
+
+                poll.opened = False
+                poll.save()
+
+                self.stdout.write('Successfully closed poll "%s"\n' % poll_id)
+
+.. note::
+    When you are using management commands and wish to provide console
+    output, you should write to ``self.stdout`` and ``self.stderr``,
+    instead of printing to ``stdout`` and ``stderr`` directly. By
+    using these proxies, it becomes much easier to test your custom
+    command.
+
+The new custom command can be called using ``python manage.py closepoll
+<poll_id>``.
+
+The ``handle()`` method takes zero or more ``poll_ids`` and sets ``poll.opened``
+to ``False`` for each one. If the user referenced any nonexistent polls, a
+:class:`CommandError` is raised. The ``poll.opened`` attribute does not exist
+in the :doc:`tutorial</intro/tutorial01>` and was added to
+``polls.models.Poll`` for this example.
+
+The same ``closepoll`` could be easily modified to delete a given poll instead
+of closing it by accepting additional command line options. These custom options
+must be added to :attr:`~BaseCommand.option_list` like this:
+
+.. code-block:: python
+
+    from optparse import make_option
+
+    class Command(BaseCommand):
+        option_list = BaseCommand.option_list + (
+            make_option('--delete',
+                action='store_true',
+                dest='delete',
+                default=False,
+                help='Delete poll instead of closing it'),
+            )
+        # ...
+
+In addition to being able to add custom command line options, all
+:doc:`management commands</ref/django-admin>` can accept some
+default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`.
+
+.. admonition:: Management commands and locales
+
+    The :meth:`BaseCommand.execute` method sets the hardcoded ``en-us`` locale
+    because the commands shipped with Django perform several tasks
+    (for example, user-facing content rendering and database population) that
+    require a system-neutral string language (for which we use ``en-us``).
+
+    If your custom management command uses another locale, you should manually
+    activate and deactivate it in your :meth:`~BaseCommand.handle` or
+    :meth:`~NoArgsCommand.handle_noargs` method using the functions provided by
+    the I18N support code:
+
+    .. code-block:: python
+
+        from django.core.management.base import BaseCommand, CommandError
+        from django.utils import translation
+
+        class Command(BaseCommand):
+            ...
+            self.can_import_settings = True
+
+            def handle(self, *args, **options):
+
+                # Activate a fixed locale, e.g. Russian
+                translation.activate('ru')
+
+                # Or you can activate the LANGUAGE_CODE
+                # chosen in the settings:
+                #
+                #from django.conf import settings
+                #translation.activate(settings.LANGUAGE_CODE)
+
+                # Your command logic here
+                # ...
+
+                translation.deactivate()
+
+    Take into account though, that system management commands typically have to
+    be very careful about running in non-uniform locales, so:
+
+    * Make sure the :setting:`USE_I18N` setting is always ``True`` when running
+      the command (this is one good example of the potential problems stemming
+      from a dynamic runtime environment that Django commands avoid offhand by
+      always using a fixed locale).
+
+    * Review the code of your command and the code it calls for behavioral
+      differences when locales are changed and evaluate its impact on
+      predictable behavior of your command.
+
+Command objects
+===============
+
+.. class:: BaseCommand
+
+The base class from which all management commands ultimately derive.
+
+Use this class if you want access to all of the mechanisms which
+parse the command-line arguments and work out what code to call in
+response; if you don't need to change any of that behavior,
+consider using one of its :ref:`subclasses<ref-basecommand-subclasses>`.
+
+Subclassing the :class:`BaseCommand` class requires that you implement the
+:meth:`~BaseCommand.handle` method.
+
+Attributes
+----------
+
+All attributes can be set in your derived class and can be used in
+:class:`BaseCommand`'s :ref:`subclasses<ref-basecommand-subclasses>`.
+
+.. attribute:: BaseCommand.args
+
+  A string listing the arguments accepted by the command,
+  suitable for use in help messages; e.g., a command which takes
+  a list of application names might set this to '<appname
+  appname ...>'.
+
+.. attribute:: BaseCommand.can_import_settings
+
+  A boolean indicating whether the command needs to be able to
+  import Django settings; if ``True``, ``execute()`` will verify
+  that this is possible before proceeding. Default value is
+  ``True``.
+
+.. attribute:: BaseCommand.help
+
+  A short description of the command, which will be printed in the
+  help message when the user runs the command
+  ``python manage.py help <command>``.
+
+.. attribute:: BaseCommand.option_list
+
+  This is the list of ``optparse`` options which will be fed
+  into the command's ``OptionParser`` for parsing arguments.
+
+.. attribute:: BaseCommand.output_transaction
+
+  A boolean indicating whether the command outputs SQL
+  statements; if ``True``, the output will automatically be
+  wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
+  ``False``.
+
+.. attribute:: BaseCommand.requires_model_validation
+
+  A boolean; if ``True``, validation of installed models will be
+  performed prior to executing the command. Default value is
+  ``True``. To validate an individual application's models
+  rather than all applications' models, call
+  :meth:`~BaseCommand.validate` from :meth:`~BaseCommand.handle`.
+
+Methods
+-------
+
+:class:`BaseCommand` has a few methods that can be overridden but only
+the :meth:`~BaseCommand.handle` method must be implemented.
+
+.. admonition:: Implementing a constructor in a subclass
+
+  If you implement ``__init__`` in your subclass of :class:`BaseCommand`,
+  you must call :class:`BaseCommand`'s ``__init__``.
+
+  .. code-block:: python
+
+    class Command(BaseCommand):
+        def __init__(self, *args, **kwargs):
+            super(Command, self).__init__(*args, **kwargs)
+            # ...
+
+.. method:: BaseCommand.get_version()
+
+    Return the Django version, which should be correct for all
+    built-in Django commands. User-supplied commands can
+    override this method to return their own version.
+
+.. method:: BaseCommand.execute(*args, **options)
+
+    Try to execute this command, performing model validation if
+    needed (as controlled by the attribute
+    :attr:`requires_model_validation`). If the command raises a
+    :class:`CommandError`, intercept it and print it sensibly to
+    stderr.
+
+.. method:: BaseCommand.handle(*args, **options)
+
+    The actual logic of the command. Subclasses must implement this method.
+
+.. _ref-basecommand-subclasses:
+
+BaseCommand subclasses
+----------------------
+
+.. class:: AppCommand
+
+A management command which takes one or more installed application
+names as arguments, and does something with each of them.
+
+Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
+:meth:`~AppCommand.handle_app`, which will be called once for each application.
+
+.. method:: AppCommand.handle_app(app, **options)
+
+    Perform the command's actions for ``app``, which will be the
+    Python module corresponding to an application name given on
+    the command line.
+
+.. class:: LabelCommand
+
+A management command which takes one or more arbitrary arguments
+(labels) on the command line, and does something with each of
+them.
+
+Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
+:meth:`~LabelCommand.handle_label`, which will be called once for each label.
+
+.. method:: LabelCommand.handle_label(label, **options)
+
+    Perform the command's actions for ``label``, which will be the
+    string as given on the command line.
+
+.. class:: NoArgsCommand
+
+A command which takes no arguments on the command line.
+
+Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
+:meth:`~NoArgsCommand.handle_noargs`; :meth:`~BaseCommand.handle` itself is
+overridden to ensure no arguments are passed to the command.
+
+.. method:: NoArgsCommand.handle_noargs(**options)
+
+    Perform this command's actions
+
+.. _ref-command-exceptions:
+
+Command exceptions
+------------------
+
+.. class:: CommandError
+
+Exception class indicating a problem while executing a management
+command.
+
+If this exception is raised during the execution of a management
+command, it will be caught and turned into a nicely-printed error
+message to the appropriate output stream (i.e., stderr); as a
+result, raising this exception (with a sensible description of the
+error) is the preferred way to indicate that something has gone
+wrong in the execution of a command.

File howto/custom-model-fields.txt

+===========================
+Writing custom model fields
+===========================
+
+.. currentmodule:: django.db.models
+
+Introduction
+============
+
+The :doc:`model reference </topics/db/models>` documentation explains how to use
+Django's standard field classes -- :class:`~django.db.models.CharField`,
+:class:`~django.db.models.DateField`, etc. For many purposes, those classes are
+all you'll need. Sometimes, though, the Django version won't meet your precise
+requirements, or you'll want to use a field that is entirely different from
+those shipped with Django.
+
+Django's built-in field types don't cover every possible database column type --
+only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure
+column types, such as geographic polygons or even user-created types such as
+`PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses.
+
+.. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html
+
+Alternatively, you may have a complex Python object that can somehow be
+serialized to fit into a standard database column type. This is another case
+where a ``Field`` subclass will help you use your object with your models.
+
+Our example object
+------------------
+
+Creating custom fields requires a bit of attention to detail. To make things
+easier to follow, we'll use a consistent example throughout this document:
+wrapping a Python object representing the deal of cards in a hand of Bridge_.
+Don't worry, you don't have know how to play Bridge to follow this example.
+You only need to know that 52 cards are dealt out equally to four players, who
+are traditionally called *north*, *east*, *south* and *west*.  Our class looks
+something like this::
+
+    class Hand(object):
+        """A hand of cards (bridge style)"""
+
+        def __init__(self, north, east, south, west):
+            # Input parameters are lists of cards ('Ah', '9s', etc)
+            self.north = north
+            self.east = east
+            self.south = south
+            self.west = west
+
+        # ... (other possibly useful methods omitted) ...
+
+.. _Bridge: http://en.wikipedia.org/wiki/Contract_bridge
+
+This is just an ordinary Python class, with nothing Django-specific about it.
+We'd like to be able to do things like this in our models (we assume the
+``hand`` attribute on the model is an instance of ``Hand``)::
+
+    example = MyModel.objects.get(pk=1)
+    print example.hand.north
+
+    new_hand = Hand(north, east, south, west)
+    example.hand = new_hand
+    example.save()
+
+We assign to and retrieve from the ``hand`` attribute in our model just like
+any other Python class. The trick is to tell Django how to handle saving and
+loading such an object.
+
+In order to use the ``Hand`` class in our models, we **do not** have to change
+this class at all. This is ideal, because it means you can easily write
+model support for existing classes where you cannot change the source code.
+
+.. note::
+    You might only be wanting to take advantage of custom database column
+    types and deal with the data as standard Python types in your models;
+    strings, or floats, for example. This case is similar to our ``Hand``
+    example and we'll note any differences as we go along.
+
+Background theory
+=================
+
+Database storage
+----------------
+
+The simplest way to think of a model field is that it provides a way to take a
+normal Python object -- string, boolean, ``datetime``, or something more
+complex like ``Hand`` -- and convert it to and from a format that is useful
+when dealing with the database (and serialization, but, as we'll see later,
+that falls out fairly naturally once you have the database side under control).
+
+Fields in a model must somehow be converted to fit into an existing database
+column type. Different databases provide different sets of valid column types,
+but the rule is still the same: those are the only types you have to work
+with. Anything you want to store in the database must fit into one of
+those types.
+
+Normally, you're either writing a Django field to match a particular database
+column type, or there's a fairly straightforward way to convert your data to,
+say, a string.
+
+For our ``Hand`` example, we could convert the card data to a string of 104
+characters by concatenating all the cards together in a pre-determined order --
+say, all the *north* cards first, then the *east*, *south* and *west* cards. So
+``Hand`` objects can be saved to text or character columns in the database.
+
+What does a field class do?
+---------------------------
+
+.. class:: Field
+
+All of Django's fields (and when we say *fields* in this document, we always
+mean model fields and not :doc:`form fields </ref/forms/fields>`) are subclasses
+of :class:`django.db.models.Field`. Most of the information that Django records
+about a field is common to all fields -- name, help text, uniqueness and so
+forth. Storing all that information is handled by ``Field``. We'll get into the
+precise details of what ``Field`` can do later on; for now, suffice it to say
+that everything descends from ``Field`` and then customizes key pieces of the
+class behavior.
+
+It's important to realize that a Django field class is not what is stored in
+your model attributes. The model attributes contain normal Python objects. The
+field classes you define in a model are actually stored in the ``Meta`` class
+when the model class is created (the precise details of how this is done are
+unimportant here). This is because the field classes aren't necessary when
+you're just creating and modifying attributes. Instead, they provide the
+machinery for converting between the attribute value and what is stored in the
+database or sent to the :doc:`serializer </topics/serialization>`.
+
+Keep this in mind when creating your own custom fields. The Django ``Field``
+subclass you write provides the machinery for converting between your Python
+instances and the database/serializer values in various ways (there are
+differences between storing a value and using a value for lookups, for
+example). If this sounds a bit tricky, don't worry -- it will become clearer in
+the examples below. Just remember that you will often end up creating two
+classes when you want a custom field:
+
+    * The first class is the Python object that your users will manipulate.
+      They will assign it to the model attribute, they will read from it for
+      displaying purposes, things like that. This is the ``Hand`` class in our
+      example.
+
+    * The second class is the ``Field`` subclass. This is the class that knows
+      how to convert your first class back and forth between its permanent
+      storage form and the Python form.
+
+Writing a field subclass
+========================
+
+When planning your :class:`~django.db.models.Field` subclass, first give some
+thought to which existing :class:`~django.db.models.Field` class your new field
+is most similar to. Can you subclass an existing Django field and save yourself
+some work? If not, you should subclass the :class:`~django.db.models.Field`
+class, from which everything is descended.
+
+Initializing your new field is a matter of separating out any arguments that are
+specific to your case from the common arguments and passing the latter to the
+:meth:`~django.db.models.Field.__init__` method of
+:class:`~django.db.models.Field` (or your parent class).
+
+In our example, we'll call our field ``HandField``. (It's a good idea to call
+your :class:`~django.db.models.Field` subclass ``<Something>Field``, so it's
+easily identifiable as a :class:`~django.db.models.Field` subclass.) It doesn't
+behave like any existing field, so we'll subclass directly from
+:class:`~django.db.models.Field`::
+
+    from django.db import models
+
+    class HandField(models.Field):
+
+        description = "A hand of cards (bridge style)"
+
+        def __init__(self, *args, **kwargs):
+            kwargs['max_length'] = 104
+            super(HandField, self).__init__(*args, **kwargs)
+
+Our ``HandField`` accepts most of the standard field options (see the list
+below), but we ensure it has a fixed length, since it only needs to hold 52
+card values plus their suits; 104 characters in total.
+
+.. note::
+    Many of Django's model fields accept options that they don't do anything
+    with. For example, you can pass both
+    :attr:`~django.db.models.Field.editable` and
+    :attr:`~django.db.models.Field.auto_now` to a
+    :class:`django.db.models.DateField` and it will simply ignore the
+    :attr:`~django.db.models.Field.editable` parameter
+    (:attr:`~django.db.models.Field.auto_now` being set implies
+    ``editable=False``). No error is raised in this case.
+
+    This behavior simplifies the field classes, because they don't need to
+    check for options that aren't necessary. They just pass all the options to
+    the parent class and then don't use them later on. It's up to you whether
+    you want your fields to be more strict about the options they select, or
+    to use the simpler, more permissive behavior of the current fields.
+
+.. method:: Field.__init__
+
+The :meth:`~django.db.models.Field.__init__` method takes the following
+parameters:
+
+    * :attr:`~django.db.models.Field.verbose_name`
+    * :attr:`~django.db.models.Field.name`
+    * :attr:`~django.db.models.Field.primary_key`
+    * :attr:`~django.db.models.Field.max_length`
+    * :attr:`~django.db.models.Field.unique`
+    * :attr:`~django.db.models.Field.blank`
+    * :attr:`~django.db.models.Field.null`
+    * :attr:`~django.db.models.Field.db_index`
+    * :attr:`~django.db.models.Field.rel`: Used for related fields (like
+      :class:`ForeignKey`). For advanced use only.
+    * :attr:`~django.db.models.Field.default`
+    * :attr:`~django.db.models.Field.editable`
+    * :attr:`~django.db.models.Field.serialize`: If ``False``, the field will
+      not be serialized when the model is passed to Django's :doc:`serializers
+      </topics/serialization>`. Defaults to ``True``.
+    * :attr:`~django.db.models.Field.unique_for_date`
+    * :attr:`~django.db.models.Field.unique_for_month`
+    * :attr:`~django.db.models.Field.unique_for_year`
+    * :attr:`~django.db.models.Field.choices`
+    * :attr:`~django.db.models.Field.help_text`
+    * :attr:`~django.db.models.Field.db_column`
+    * :attr:`~django.db.models.Field.db_tablespace`: Currently only used with
+      the Oracle backend and only for index creation. You can usually ignore
+      this option.
+    * :attr:`~django.db.models.Field.auto_created`: True if the field was
+      automatically created, as for the `OneToOneField` used by model
+      inheritance. For advanced use only.
+
+All of the options without an explanation in the above list have the same
+meaning they do for normal Django fields. See the :doc:`field documentation
+</ref/models/fields>` for examples and details.
+
+The ``SubfieldBase`` metaclass
+------------------------------
+
+.. class:: django.db.models.SubfieldBase
+
+As we indicated in the introduction_, field subclasses are often needed for
+two reasons: either to take advantage of a custom database column type, or to
+handle complex Python types. Obviously, a combination of the two is also
+possible. If you're only working with custom database column types and your
+model fields appear in Python as standard Python types direct from the
+database backend, you don't need to worry about this section.
+
+If you're handling custom Python types, such as our ``Hand`` class, we need to
+make sure that when Django initializes an instance of our model and assigns a
+database value to our custom field attribute, we convert that value into the
+appropriate Python object. The details of how this happens internally are a
+little complex, but the code you need to write in your ``Field`` class is
+simple: make sure your field subclass uses a special metaclass:
+
+For example::
+
+    class HandField(models.Field):
+
+        description = "A hand of cards (bridge style)"
+
+        __metaclass__ = models.SubfieldBase
+
+        def __init__(self, *args, **kwargs):
+            # ...
+
+This ensures that the :meth:`.to_python` method, documented below, will always
+be called when the attribute is initialized.
+
+ModelForms and custom fields
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you use :class:`~django.db.models.SubfieldBase`, :meth:`.to_python`
+will be called every time an instance of the field is assigned a
+value. This means that whenever a value may be assigned to the field,
+you need to ensure that it will be of the correct datatype, or that
+you handle any exceptions.
+
+This is especially important if you use :doc:`ModelForms
+</topics/forms/modelforms>`. When saving a ModelForm, Django will use
+form values to instantiate model instances. However, if the cleaned
+form data can't be used as valid input to the field, the normal form
+validation process will break.
+
+Therefore, you must ensure that the form field used to represent your
+custom field performs whatever input validation and data cleaning is
+necessary to convert user-provided form input into a
+`to_python()`-compatible model field value. This may require writing a
+custom form field, and/or implementing the :meth:`.formfield` method on
+your field to return a form field class whose `to_python()` returns the
+correct datatype.
+
+Documenting your custom field
+-----------------------------
+
+.. attribute:: Field.description
+
+As always, you should document your field type, so users will know what it is.
+In addition to providing a docstring for it, which is useful for developers,
+you can also allow users of the admin app to see a short description of the
+field type via the :doc:`django.contrib.admindocs
+</ref/contrib/admin/admindocs>` application. To do this simply provide
+descriptive text in a ``description`` class attribute of your custom field. In
+the above example, the description displayed by the ``admindocs``
+application for a ``HandField`` will be 'A hand of cards (bridge style)'.
+
+Useful methods
+--------------
+
+Once you've created your :class:`~django.db.models.Field` subclass and set up
+the ``__metaclass__``, you might consider overriding a few standard methods,
+depending on your field's behavior. The list of methods below is in
+approximately decreasing order of importance, so start from the top.
+
+Custom database types
+~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.db_type(self, connection)
+
+.. versionadded:: 1.2
+   The ``connection`` argument was added to support multiple databases.
+
+Returns the database column data type for the :class:`~django.db.models.Field`,
+taking into account the connection object, and the settings associated with it.
+
+Say you've created a PostgreSQL custom type called ``mytype``. You can use this
+field with Django by subclassing ``Field`` and implementing the
+:meth:`.db_type` method, like so::
+
+    from django.db import models
+
+    class MytypeField(models.Field):
+        def db_type(self, connection):
+            return 'mytype'
+
+Once you have ``MytypeField``, you can use it in any model, just like any other
+``Field`` type::
+
+    class Person(models.Model):
+        name = models.CharField(max_length=80)
+        gender = models.CharField(max_length=1)
+        something_else = MytypeField()
+
+If you aim to build a database-agnostic application, you should account for
+differences in database column types. For example, the date/time column type
+in PostgreSQL is called ``timestamp``, while the same column in MySQL is called
+``datetime``. The simplest way to handle this in a :meth:`.db_type`
+method is to check the ``connection.settings_dict['ENGINE']`` attribute.
+
+For example::
+
+    class MyDateField(models.Field):
+        def db_type(self, connection):
+            if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
+                return 'datetime'
+            else:
+                return 'timestamp'
+
+The :meth:`.db_type` method is only called by Django when the framework
+constructs the ``CREATE TABLE`` statements for your application -- that is,
+when you first create your tables. It's not called at any other time, so it can
+afford to execute slightly complex code, such as the
+``connection.settings_dict`` check in the above example.
+
+Some database column types accept parameters, such as ``CHAR(25)``, where the
+parameter ``25`` represents the maximum column length. In cases like these,
+it's more flexible if the parameter is specified in the model rather than being
+hard-coded in the ``db_type()`` method. For example, it wouldn't make much
+sense to have a ``CharMaxlength25Field``, shown here::
+
+    # This is a silly example of hard-coded parameters.
+    class CharMaxlength25Field(models.Field):
+        def db_type(self, connection):
+            return 'char(25)'
+
+    # In the model:
+    class MyModel(models.Model):
+        # ...
+        my_field = CharMaxlength25Field()
+
+The better way of doing this would be to make the parameter specifiable at run
+time -- i.e., when the class is instantiated. To do that, just implement
+:meth:`django.db.models.Field.__init__`, like so::
+
+    # This is a much more flexible example.
+    class BetterCharField(models.Field):
+        def __init__(self, max_length, *args, **kwargs):
+            self.max_length = max_length
+            super(BetterCharField, self).__init__(*args, **kwargs)
+
+        def db_type(self, connection):
+            return 'char(%s)' % self.max_length
+
+    # In the model:
+    class MyModel(models.Model):
+        # ...
+        my_field = BetterCharField(25)
+
+Finally, if your column requires truly complex SQL setup, return ``None`` from
+:meth:`.db_type`. This will cause Django's SQL creation code to skip
+over this field. You are then responsible for creating the column in the right
+table in some other way, of course, but this gives you a way to tell Django to
+get out of the way.
+
+Converting database values to Python objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.to_python(self, value)
+
+Converts a value as returned by your database (or a serializer) to a Python
+object.
+
+The default implementation simply returns ``value``, for the common case in
+which the database backend already returns data in the correct format (as a
+Python string, for example).
+
+If your custom :class:`~django.db.models.Field` class deals with data structures
+that are more complex than strings, dates, integers or floats, then you'll need
+to override this method. As a general rule, the method should deal gracefully
+with any of the following arguments:
+
+    * An instance of the correct type (e.g., ``Hand`` in our ongoing example).
+
+    * A string (e.g., from a deserializer).
+
+    * Whatever the database returns for the column type you're using.
+
+In our ``HandField`` class, we're storing the data as a VARCHAR field in the
+database, so we need to be able to process strings and ``Hand`` instances in
+:meth:`.to_python`::
+
+    import re
+
+    class HandField(models.Field):
+        # ...
+
+        def to_python(self, value):
+            if isinstance(value, Hand):
+                return value
+
+            # The string case.
+            p1 = re.compile('.{26}')
+            p2 = re.compile('..')
+            args = [p2.findall(x) for x in p1.findall(value)]
+            return Hand(*args)
+
+Notice that we always return a ``Hand`` instance from this method. That's the
+Python object type we want to store in the model's attribute.
+
+**Remember:** If your custom field needs the :meth:`to_python` method to be
+called when it is created, you should be using `The SubfieldBase metaclass`_
+mentioned earlier. Otherwise :meth:`.to_python` won't be called
+automatically.
+
+Converting Python objects to query values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.get_prep_value(self, value)
+
+.. versionadded:: 1.2
+   This method was factored out of ``get_db_prep_value()``
+
+This is the reverse of :meth:`.to_python` when working with the
+database backends (as opposed to serialization). The ``value``
+parameter is the current value of the model's attribute (a field has
+no reference to its containing model, so it cannot retrieve the value
+itself), and the method should return data in a format that has been
+prepared for use as a parameter in a query.
+
+This conversion should *not* include any database-specific
+conversions. If database-specific conversions are required, they
+should be made in the call to :meth:`.get_db_prep_value`.
+
+For example::
+
+    class HandField(models.Field):
+        # ...
+
+        def get_prep_value(self, value):
+            return ''.join([''.join(l) for l in (value.north,
+                    value.east, value.south, value.west)])
+
+Converting query values to database values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.get_db_prep_value(self, value, connection, prepared=False)
+
+.. versionadded:: 1.2
+   The ``connection`` and ``prepared`` arguments were added to support multiple databases.
+
+Some data types (for example, dates) need to be in a specific format
+before they can be used by a database backend.
+:meth:`.get_db_prep_value` is the method where those conversions should
+be made. The specific connection that will be used for the query is
+passed as the ``connection`` parameter. This allows you to use
+backend-specific conversion logic if it is required.
+
+The ``prepared`` argument describes whether or not the value has
+already been passed through :meth:`.get_prep_value` conversions. When
+``prepared`` is False, the default implementation of
+:meth:`.get_db_prep_value` will call :meth:`.get_prep_value` to do
+initial data conversions before performing any database-specific
+processing.
+
+.. method:: Field.get_db_prep_save(self, value, connection)
+
+.. versionadded:: 1.2
+   The ``connection`` argument was added to support multiple databases.
+
+Same as the above, but called when the Field value must be *saved* to
+the database. As the default implementation just calls
+:meth:`.get_db_prep_value`, you shouldn't need to implement this method
+unless your custom field needs a special conversion when being saved
+that is not the same as the conversion used for normal query
+parameters (which is implemented by :meth:`.get_db_prep_value`).
+
+Preprocessing values before saving
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.pre_save(self, model_instance, add)
+
+This method is called just prior to :meth:`.get_db_prep_save` and should return
+the value of the appropriate attribute from ``model_instance`` for this field.
+The attribute name is in ``self.attname`` (this is set up by
+:class:`~django.db.models.Field`). If the model is being saved to the database
+for the first time, the ``add`` parameter will be ``True``, otherwise it will be
+``False``.
+
+You only need to override this method if you want to preprocess the value
+somehow, just before saving. For example, Django's
+:class:`~django.db.models.DateTimeField` uses this method to set the attribute
+correctly in the case of :attr:`~django.db.models.Field.auto_now` or
+:attr:`~django.db.models.Field.auto_now_add`.
+
+If you do override this method, you must return the value of the attribute at
+the end. You should also update the model's attribute if you make any changes
+to the value so that code holding references to the model will always see the
+correct value.
+
+Preparing values for use in database lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As with value conversions, preparing a value for database lookups is a
+two phase process.
+
+.. method:: Field.get_prep_lookup(self, lookup_type, value)
+
+.. versionadded:: 1.2
+   This method was factored out of ``get_db_prep_lookup()``
+
+:meth:`.get_prep_lookup` performs the first phase of lookup preparation,
+performing generic data validity checks
+
+Prepares the ``value`` for passing to the database when used in a lookup (a
+``WHERE`` constraint in SQL). The ``lookup_type`` will be one of the valid
+Django filter lookups: ``exact``, ``iexact``, ``contains``, ``icontains``,
+``gt``, ``gte``, ``lt``, ``lte``, ``in``, ``startswith``, ``istartswith``,
+``endswith``, ``iendswith``, ``range``, ``year``, ``month``, ``day``,
+``isnull``, ``search``, ``regex``, and ``iregex``.
+
+Your method must be prepared to handle all of these ``lookup_type`` values and
+should raise either a ``ValueError`` if the ``value`` is of the wrong sort (a
+list when you were expecting an object, for example) or a ``TypeError`` if
+your field does not support that type of lookup. For many fields, you can get
+by with handling the lookup types that need special handling for your field
+and pass the rest to the :meth:`.get_db_prep_lookup` method of the parent class.
+
+If you needed to implement ``get_db_prep_save()``, you will usually need to
+implement ``get_prep_lookup()``. If you don't, ``get_prep_value`` will be
+called by the default implementation, to manage ``exact``, ``gt``, ``gte``,
+``lt``, ``lte``, ``in`` and ``range`` lookups.
+
+You may also want to implement this method to limit the lookup types that could
+be used with your custom field type.
+
+Note that, for ``range`` and ``in`` lookups, ``get_prep_lookup`` will receive
+a list of objects (presumably of the right type) and will need to convert them
+to a list of things of the right type for passing to the database. Most of the
+time, you can reuse ``get_prep_value()``, or at least factor out some common
+pieces.
+
+For example, the following code implements ``get_prep_lookup`` to limit the
+accepted lookup types to ``exact`` and ``in``::
+
+    class HandField(models.Field):
+        # ...
+
+        def get_prep_lookup(self, lookup_type, value):
+            # We only handle 'exact' and 'in'. All others are errors.
+            if lookup_type == 'exact':
+                return self.get_prep_value(value)
+            elif lookup_type == 'in':
+                return [self.get_prep_value(v) for v in value]
+            else:
+                raise TypeError('Lookup type %r not supported.' % lookup_type)
+
+.. method:: Field.get_db_prep_lookup(self, lookup_type, value, connection, prepared=False)
+
+.. versionadded:: 1.2
+   The ``connection`` and ``prepared`` arguments were added to support multiple databases.
+
+Performs any database-specific data conversions required by a lookup.
+As with :meth:`.get_db_prep_value`, the specific connection that will
+be used for the query is passed as the ``connection`` parameter.
+The ``prepared`` argument describes whether the value has already been
+prepared with :meth:`.get_prep_lookup`.
+
+Specifying the form field for a model field
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.formfield(self, form_class=forms.CharField, **kwargs)
+
+Returns the default form field to use when this field is displayed in a model.
+This method is called by the :class:`~django.forms.ModelForm` helper.
+
+All of the ``kwargs`` dictionary is passed directly to the form field's
+:meth:`~django.forms.Field__init__` method. Normally, all you need to do is
+set up a good default for the ``form_class`` argument and then delegate further
+handling to the parent class. This might require you to write a custom form
+field (and even a form widget). See the :doc:`forms documentation
+</topics/forms/index>` for information about this, and take a look at the code in
+:mod:`django.contrib.localflavor` for some examples of custom widgets.
+
+Continuing our ongoing example, we can write the :meth:`.formfield` method as::
+
+    class HandField(models.Field):
+        # ...
+
+        def formfield(self, **kwargs):
+            # This is a fairly standard way to set up some defaults
+            # while letting the caller override them.
+            defaults = {'form_class': MyFormField}
+            defaults.update(kwargs)
+            return super(HandField, self).formfield(**defaults)
+
+This assumes we've imported a ``MyFormField`` field class (which has its own
+default widget). This document doesn't cover the details of writing custom form
+fields.
+
+.. _helper functions: ../forms/#generating-forms-for-models
+.. _forms documentation: ../forms/
+
+Emulating built-in field types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.get_internal_type(self)
+
+Returns a string giving the name of the :class:`~django.db.models.Field`
+subclass we are emulating at the database level. This is used to determine the
+type of database column for simple cases.
+
+If you have created a :meth:`.db_type` method, you don't need to worry about
+:meth:`.get_internal_type` -- it won't be used much. Sometimes, though, your
+database storage is similar in type to some other field, so you can use that
+other field's logic to create the right column.
+
+For example::
+
+    class HandField(models.Field):
+        # ...
+
+        def get_internal_type(self):
+            return 'CharField'
+
+No matter which database backend we are using, this will mean that ``syncdb``
+and other SQL commands create the right column type for storing a string.
+
+If :meth:`.get_internal_type` returns a string that is not known to Django for
+the database backend you are using -- that is, it doesn't appear in
+``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still be
+used by the serializer, but the default :meth:`.db_type` method will return
+``None``. See the documentation of :meth:`.db_type` for reasons why this might be
+useful. Putting a descriptive string in as the type of the field for the
+serializer is a useful idea if you're ever going to be using the serializer
+output in some other place, outside of Django.
+
+Converting field data for serialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: Field.value_to_string(self, obj)
+
+This method is used by the serializers to convert the field into a string for
+output. Calling :meth:`Field._get_val_from_obj(obj)` is the best way to get the
+value to serialize. For example, since our ``HandField`` uses strings for its
+data storage anyway, we can reuse some existing conversion code::
+
+    class HandField(models.Field):
+        # ...
+
+        def value_to_string(self, obj):
+            value = self._get_val_from_obj(obj)
+            return self.get_db_prep_value(value)
+
+Some general advice
+--------------------
+
+Writing a custom field can be a tricky process, particularly if you're doing
+complex conversions between your Python types and your database and
+serialization formats. Here are a couple of tips to make things go more
+smoothly:
+
+    1. Look at the existing Django fields (in
+       :file:`django/db/models/fields/__init__.py`) for inspiration. Try to find
+       a field that's similar to what you want and extend it a little bit,
+       instead of creating an entirely new field from scratch.
+
+    2. Put a :meth:`__str__` or :meth:`__unicode__` method on the class you're
+       wrapping up as a field. There are a lot of places where the default
+       behavior of the field code is to call
+       :func:`~django.utils.encoding.force_unicode` on the value. (In our
+       examples in this document, ``value`` would be a ``Hand`` instance, not a
+       ``HandField``). So if your :meth:`__unicode__` method automatically
+       converts to the string form of your Python object, you can save yourself
+       a lot of work.
+
+
+Writing a ``FileField`` subclass
+=================================
+
+In addition to the above methods, fields that deal with files have a few other
+special requirements which must be taken into account. The majority of the
+mechanics provided by ``FileField``, such as controlling database storage and
+retrieval, can remain unchanged, leaving subclasses to deal with the challenge
+of supporting a particular type of file.
+
+Django provides a ``File`` class, which is used as a proxy to the file's
+contents and operations. This can be subclassed to customize how the file is
+accessed, and what methods are available. It lives at
+``django.db.models.fields.files``, and its default behavior is explained in the
+:doc:`file documentation </ref/files/file>`.
+
+Once a subclass of ``File`` is created, the new ``FileField`` subclass must be
+told to use it. To do so, simply assign the new ``File`` subclass to the special
+``attr_class`` attribute of the ``FileField`` subclass.
+
+A few suggestions
+------------------
+
+In addition to the above details, there are a few guidelines which can greatly
+improve the efficiency and readability of the field's code.
+
+    1. The source for Django's own ``ImageField`` (in
+       ``django/db/models/fields/files.py``) is a great example of how to
+       subclass ``FileField`` to support a particular type of file, as it
+       incorporates all of the techniques described above.
+
+    2. Cache file attributes wherever possible. Since files may be stored in
+       remote storage systems, retrieving them may cost extra time, or even
+       money, that isn't always necessary. Once a file is retrieved to obtain
+       some data about its content, cache as much of that data as possible to
+       reduce the number of times the file must be retrieved on subsequent
+       calls for that information.

File howto/custom-template-tags.txt

+================================
+Custom template tags and filters
+================================
+
+Introduction
+============
+
+Django's template system comes with a wide variety of :doc:`built-in
+tags and filters </ref/templates/builtins>` designed to address the
+presentation logic needs of your application. Nevertheless, you may
+find yourself needing functionality that is not covered by the core
+set of template primitives. You can extend the template engine by
+defining custom tags and filters using Python, and then make them
+available to your templates using the ``{% load %}`` tag.
+
+Code layout
+-----------
+
+Custom template tags and filters must live inside a Django app. If they relate
+to an existing app it makes sense to bundle them there; otherwise, you should
+create a new app to hold them.
+
+The app should contain a ``templatetags`` directory, at the same level as
+``models.py``, ``views.py``, etc. If this doesn't already exist, create it -
+don't forget the ``__init__.py`` file to ensure the directory is treated as a
+Python package.
+
+Your custom tags and filters will live in a module inside the ``templatetags``
+directory. The name of the module file is the name you'll use to load the tags
+later, so be careful to pick a name that won't clash with custom tags and
+filters in another app.
+
+For example, if your custom tags/filters are in a file called
+``poll_extras.py``, your app layout might look like this::
+
+    polls/
+        models.py
+        templatetags/
+            __init__.py
+            poll_extras.py
+        views.py
+
+And in your template you would use the following:
+
+.. code-block:: html+django
+
+    {% load poll_extras %}
+
+The app that contains the custom tags must be in :setting:`INSTALLED_APPS` in
+order for the ``{% load %}`` tag to work. This is a security feature: It allows
+you to host Python code for many template libraries on a single host machine
+without enabling access to all of them for every Django installation.
+
+There's no limit on how many modules you put in the ``templatetags`` package.
+Just keep in mind that a ``{% load %}`` statement will load tags/filters for
+the given Python module name, not the name of the app.
+
+To be a valid tag library, the module must contain a module-level variable
+named ``register`` that is a ``template.Library`` instance, in which all the
+tags and filters are registered. So, near the top of your module, put the
+following::
+
+    from django import template
+
+    register = template.Library()
+
+.. admonition:: Behind the scenes
+
+    For a ton of examples, read the source code for Django's default filters
+    and tags. They're in ``django/template/defaultfilters.py`` and
+    ``django/template/defaulttags.py``, respectively.
+
+Writing custom template filters
+-------------------------------
+
+Custom filters are just Python functions that take one or two arguments:
+
+    * The value of the variable (input) -- not necessarily a string.
+    * The value of the argument -- this can have a default value, or be left
+      out altogether.
+
+For example, in the filter ``{{ var|foo:"bar" }}``, the filter ``foo`` would be
+passed the variable ``var`` and the argument ``"bar"``.
+
+Filter functions should always return something. They shouldn't raise
+exceptions. They should fail silently. In case of error, they should return
+either the original input or an empty string -- whichever makes more sense.
+
+Here's an example filter definition::
+
+    def cut(value, arg):
+        "Removes all values of arg from the given string"
+        return value.replace(arg, '')
+
+And here's an example of how that filter would be used:
+
+.. code-block:: html+django
+
+    {{ somevariable|cut:"0" }}
+
+Most filters don't take arguments. In this case, just leave the argument out of
+your function. Example::
+
+    def lower(value): # Only one argument.
+        "Converts a string into all lowercase"
+        return value.lower()
+
+Template filters that expect strings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you're writing a template filter that only expects a string as the first
+argument, you should use the decorator ``stringfilter``. This will
+convert an object to its string value before being passed to your function::
+
+    from django.template.defaultfilters import stringfilter
+
+    @stringfilter
+    def lower(value):
+        return value.lower()
+
+This way, you'll be able to pass, say, an integer to this filter, and it
+won't cause an ``AttributeError`` (because integers don't have ``lower()``
+methods).
+
+Registering custom filters
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you've written your filter definition, you need to register it with
+your ``Library`` instance, to make it available to Django's template language::
+
+    register.filter('cut', cut)
+    register.filter('lower', lower)
+
+The ``Library.filter()`` method takes two arguments:
+
+    1. The name of the filter -- a string.
+    2. The compilation function -- a Python function (not the name of the
+       function as a string).
+
+You can use ``register.filter()`` as a decorator instead::
+
+    @register.filter(name='cut')
+    @stringfilter
+    def cut(value, arg):
+        return value.replace(arg, '')
+
+    @register.filter
+    @stringfilter
+    def lower(value):
+        return value.lower()
+
+If you leave off the ``name`` argument, as in the second example above, Django
+will use the function's name as the filter name.
+
+Filters and auto-escaping
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When writing a custom filter, give some thought to how the filter will interact
+with Django's auto-escaping behavior. Note that three types of strings can be
+passed around inside the template code:
+
+    * **Raw strings** are the native Python ``str`` or ``unicode`` types. On
+      output, they're escaped if auto-escaping is in effect and presented
+      unchanged, otherwise.
+
+    * **Safe strings** are strings that have been marked safe from further
+      escaping at output time. Any necessary escaping has already been done.
+      They're commonly used for output that contains raw HTML that is intended
+      to be interpreted as-is on the client side.
+
+      Internally, these strings are of type ``SafeString`` or ``SafeUnicode``.
+      They share a common base class of ``SafeData``, so you can test
+      for them using code like::
+
+          if isinstance(value, SafeData):
+              # Do something with the "safe" string.
+
+    * **Strings marked as "needing escaping"** are *always* escaped on
+      output, regardless of whether they are in an ``autoescape`` block or not.
+      These strings are only escaped once, however, even if auto-escaping
+      applies.
+
+      Internally, these strings are of type ``EscapeString`` or
+      ``EscapeUnicode``. Generally you don't have to worry about these; they
+      exist for the implementation of the ``escape`` filter.
+
+Template filter code falls into one of two situations:
+
+    1. Your filter does not introduce any HTML-unsafe characters (``<``, ``>``,
+       ``'``, ``"`` or ``&``) into the result that were not already present. In
+       this case, you can let Django take care of all the auto-escaping
+       handling for you. All you need to do is put the ``is_safe`` attribute on
+       your filter function and set it to ``True``, like so::
+
+           @register.filter
+           def myfilter(value):
+               return value
+           myfilter.is_safe = True
+
+       This attribute tells Django that if a "safe" string is passed into your
+       filter, the result will still be "safe" and if a non-safe string is
+       passed in, Django will automatically escape it, if necessary.
+
+       You can think of this as meaning "this filter is safe -- it doesn't
+       introduce any possibility of unsafe HTML."
+
+       The reason ``is_safe`` is necessary is because there are plenty of
+       normal string operations that will turn a ``SafeData`` object back into
+       a normal ``str`` or ``unicode`` object and, rather than try to catch
+       them all, which would be very difficult, Django repairs the damage after
+       the filter has completed.
+
+       For example, suppose you have a filter that adds the string ``xx`` to the
+       end of any input. Since this introduces no dangerous HTML characters to
+       the result (aside from any that were already present), you should mark
+       your filter with ``is_safe``::
+
+           @register.filter
+           def add_xx(value):
+               return '%sxx' % value
+           add_xx.is_safe = True
+
+       When this filter is used in a template where auto-escaping is enabled,
+       Django will escape the output whenever the input is not already marked as
+       "safe".
+
+       By default, ``is_safe`` defaults to ``False``, and you can omit it from
+       any filters where it isn't required.
+
+       Be careful when deciding if your filter really does leave safe strings
+       as safe. If you're *removing* characters, you might inadvertently leave
+       unbalanced HTML tags or entities in the result. For example, removing a
+       ``>`` from the input might turn ``<a>`` into ``<a``, which would need to
+       be escaped on output to avoid causing problems. Similarly, removing a
+       semicolon (``;``) can turn ``&amp;`` into ``&amp``, which is no longer a
+       valid entity and thus needs further escaping. Most cases won't be nearly
+       this tricky, but keep an eye out for any problems like that when
+       reviewing your code.
+
+       Marking a filter ``is_safe`` will coerce the filter's return value to
+       a string.  If your filter should return a boolean or other non-string
+       value, marking it ``is_safe`` will probably have unintended
+       consequences (such as converting a boolean False to the string
+       'False').
+
+    2. Alternatively, your filter code can manually take care of any necessary
+       escaping. This is necessary when you're introducing new HTML markup into
+       the result. You want to mark the output as safe from further
+       escaping so that your HTML markup isn't escaped further, so you'll need
+       to handle the input yourself.
+
+       To mark the output as a safe string, use
+       :func:`django.utils.safestring.mark_safe`.
+
+       Be careful, though. You need to do more than just mark the output as
+       safe. You need to ensure it really *is* safe, and what you do depends on
+       whether auto-escaping is in effect. The idea is to write filters than
+       can operate in templates where auto-escaping is either on or off in
+       order to make things easier for your template authors.
+
+       In order for your filter to know the current auto-escaping state, set
+       the ``needs_autoescape`` attribute to ``True`` on your function. (If you
+       don't specify this attribute, it defaults to ``False``). This attribute
+       tells Django that your filter function wants to be passed an extra
+       keyword argument, called ``autoescape``, that is ``True`` if
+       auto-escaping is in effect and ``False`` otherwise.
+
+       For example, let's write a filter that emphasizes the first character of
+       a string::
+
+           from django.utils.html import conditional_escape
+           from django.utils.safestring import mark_safe
+
+           def initial_letter_filter(text, autoescape=None):
+               first, other = text[0], text[1:]
+               if autoescape:
+                   esc = conditional_escape
+               else:
+                   esc = lambda x: x
+               result = '<strong>%s</strong>%s' % (esc(first), esc(other))
+               return mark_safe(result)
+           initial_letter_filter.needs_autoescape = True
+
+       The ``needs_autoescape`` attribute on the filter function and the
+       ``autoescape`` keyword argument mean that our function will know whether
+       automatic escaping is in effect when the filter is called. We use
+       ``autoescape`` to decide whether the input data needs to be passed
+       through ``django.utils.html.conditional_escape`` or not. (In the latter
+       case, we just use the identity function as the "escape" function.) The
+       ``conditional_escape()`` function is like ``escape()`` except it only
+       escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
+       instance is passed to ``conditional_escape()``, the data is returned
+       unchanged.
+
+       Finally, in the above example, we remember to mark the result as safe
+       so that our HTML is inserted directly into the template without further
+       escaping.
+
+       There's no need to worry about the ``is_safe`` attribute in this case
+       (although including it wouldn't hurt anything). Whenever you manually
+       handle the auto-escaping issues and return a safe string, the
+       ``is_safe`` attribute won't change anything either way.
+
+Writing custom template tags
+----------------------------
+
+Tags are more complex than filters, because tags can do anything.
+
+A quick overview
+~~~~~~~~~~~~~~~~
+
+Above, this document explained that the template system works in a two-step
+process: compiling and rendering. To define a custom template tag, you specify
+how the compilation works and how the rendering works.
+
+When Django compiles a template, it splits the raw template text into
+''nodes''. Each node is an instance of ``django.template.Node`` and has
+a ``render()`` method. A compiled template is, simply, a list of ``Node``
+objects. When you call ``render()`` on a compiled template object, the template
+calls ``render()`` on each ``Node`` in its node list, with the given context.
+The results are all concatenated together to form the output of the template.
+
+Thus, to define a custom template tag, you specify how the raw template tag is
+converted into a ``Node`` (the compilation function), and what the node's
+``render()`` method does.
+
+Writing the compilation function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For each template tag the template parser encounters, it calls a Python
+function with the tag contents and the parser object itself. This function is
+responsible for returning a ``Node`` instance based on the contents of the tag.
+
+For example, let's write a template tag, ``{% current_time %}``, that displays
+the current date/time, formatted according to a parameter given in the tag, in
+`strftime syntax`_. It's a good idea to decide the tag syntax before anything
+else. In our case, let's say the tag should be used like this:
+
+.. code-block:: html+django
+
+    <p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
+
+.. _`strftime syntax`: http://docs.python.org/library/time.html#time.strftime
+
+The parser for this function should grab the parameter and create a ``Node``
+object::
+
+    from django import template
+    def do_current_time(parser, token):
+        try:
+            # split_contents() knows not to split quoted strings.
+            tag_name, format_string = token.split_contents()
+        except ValueError:
+            raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0])
+        if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
+            raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name)
+        return CurrentTimeNode(format_string[1:-1])
+
+Notes:
+
+    * ``parser`` is the template parser object. We don't need it in this
+      example.
+
+    * ``token.contents`` is a string of the raw contents of the tag. In our
+      example, it's ``'current_time "%Y-%m-%d %I:%M %p"'``.
+
+    * The ``token.split_contents()`` method separates the arguments on spaces
+      while keeping quoted strings together. The more straightforward
+      ``token.contents.split()`` wouldn't be as robust, as it would naively
+      split on *all* spaces, including those within quoted strings. It's a good
+      idea to always use ``token.split_contents()``.
+
+    * This function is responsible for raising
+      ``django.template.TemplateSyntaxError``, with helpful messages, for
+      any syntax error.
+
+    * The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable.
+      Don't hard-code the tag's name in your error messages, because that
+      couples the tag's name to your function. ``token.contents.split()[0]``
+      will ''always'' be the name of your tag -- even when the tag has no
+      arguments.
+
+    * The function returns a ``CurrentTimeNode`` with everything the node needs
+      to know about this tag. In this case, it just passes the argument --
+      ``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the
+      template tag are removed in ``format_string[1:-1]``.
+
+    * The parsing is very low-level. The Django developers have experimented
+      with writing small frameworks on top of this parsing system, using
+      techniques such as EBNF grammars, but those experiments made the template
+      engine too slow. It's low-level because that's fastest.
+
+Writing the renderer
+~~~~~~~~~~~~~~~~~~~~
+
+The second step in writing custom tags is to define a ``Node`` subclass that
+has a ``render()`` method.
+
+Continuing the above example, we need to define ``CurrentTimeNode``::
+
+    from django import template
+    import datetime
+    class CurrentTimeNode(template.Node):
+        def __init__(self, format_string):
+            self.format_string = format_string
+        def render(self, context):
+            return datetime.datetime.now().strftime(self.format_string)
+
+Notes:
+
+    * ``__init__()`` gets the ``format_string`` from ``do_current_time()``.
+      Always pass any options/parameters/arguments to a ``Node`` via its
+      ``__init__()``.
+
+    * The ``render()`` method is where the work actually happens.
+
+    * ``render()`` should never raise ``TemplateSyntaxError`` or any other
+      exception. It should fail silently, just as template filters should.
+
+Ultimately, this decoupling of compilation and rendering results in an
+efficient template system, because a template can render multiple contexts
+without having to be parsed multiple times.
+
+Auto-escaping considerations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The output from template tags is **not** automatically run through the
+auto-escaping filters. However, there are still a couple of things you should
+keep in mind when writing a template tag.
+
+If the ``render()`` function of your template stores the result in a context
+variable (rather than returning the result in a string), it should take care
+to call ``mark_safe()`` if appropriate. When the variable is ultimately
+rendered, it will be affected by the auto-escape setting in effect at the
+time, so content that should be safe from further escaping needs to be marked
+as such.
+
+Also, if your template tag creates a new context for performing some
+sub-rendering, set the auto-escape attribute to the current context's value.
+The ``__init__`` method for the ``Context`` class takes a parameter called
+``autoescape`` that you can use for this purpose. For example::
+
+    def render(self, context):
+        # ...
+        new_context = Context({'var': obj}, autoescape=context.autoescape)
+        # ... Do something with new_context ...
+
+This is not a very common situation, but it's useful if you're rendering a
+template yourself. For example::
+
+    def render(self, context):
+        t = template.loader.get_template('small_fragment.html')
+        return t.render(Context({'var': obj}, autoescape=context.autoescape))
+
+If we had neglected to pass in the current ``context.autoescape`` value to our
+new ``Context`` in this example, the results would have *always* been
+automatically escaped, which may not be the desired behavior if the template
+tag is used inside a ``{% autoescape off %}`` block.
+
+.. _template_tag_thread_safety:
+
+Thread-safety considerations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.2
+
+Once a node is parsed, its ``render`` method may be called any number of times.
+Since Django is sometimes run in multi-threaded environments, a single node may
+be simultaneously rendering with different contexts in response to two separate
+requests. Therefore, it's important to make sure your template tags are thread
+safe.
+
+To make sure your template tags are thread safe, you should never store state
+information on the node itself. For example, Django provides a builtin ``cycle``
+template tag that cycles among a list of given strings each time it's rendered::
+
+    {% for o in some_list %}
+        <tr class="{% cycle 'row1' 'row2' %}>
+            ...
+        </tr>
+    {% endfor %}
+
+A naive implementation of ``CycleNode`` might look something like this::
+
+    class CycleNode(Node):
+        def __init__(self, cyclevars):
+            self.cycle_iter = itertools.cycle(cyclevars)
+        def render(self, context):
+            return self.cycle_iter.next()
+
+But, suppose we have two templates rendering the template snippet from above at
+the same time:
+
+    1. Thread 1 performs its first loop iteration, ``CycleNode.render()``
+       returns 'row1'
+    2. Thread 2 performs its first loop iteration, ``CycleNode.render()``
+       returns 'row2'
+    3. Thread 1 performs its second loop iteration, ``CycleNode.render()``
+       returns 'row1'
+    4. Thread 2 performs its second loop iteration, ``CycleNode.render()``
+       returns 'row2'
+
+The CycleNode is iterating, but it's iterating globally. As far as Thread 1
+and Thread 2 are concerned, it's always returning the same value. This is
+obviously not what we want!
+
+To address this problem, Django provides a ``render_context`` that's associated
+with the ``context`` of the template that is currently being rendered. The
+``render_context`` behaves like a Python dictionary, and should be used to store
+``Node`` state between invocations of the ``render`` method.
+
+Let's refactor our ``CycleNode`` implementation to use the ``render_context``::
+
+    class CycleNode(Node):
+        def __init__(self, cyclevars):
+            self.cyclevars = cyclevars
+        def render(self, context):
+            if self not in context.render_context:
+                context.render_context[self] = itertools.cycle(self.cyclevars)
+            cycle_iter = context.render_context[self]
+            return cycle_iter.next()
+
+Note that it's perfectly safe to store global information that will not change
+throughout the life of the ``Node`` as an attribute. In the case of
+``CycleNode``, the ``cyclevars`` argument doesn't change after the ``Node`` is
+instantiated, so we don't need to put it in the ``render_context``. But state
+information that is specific to the template that is currently being rendered,
+like the current iteration of the ``CycleNode``, should be stored in the
+``render_context``.
+
+.. note::
+    Notice how we used ``self`` to scope the ``CycleNode`` specific information
+    within the ``render_context``. There may be multiple ``CycleNodes`` in a
+    given template, so we need to be careful not to clobber another node's state
+    information. The easiest way to do this is to always use ``self`` as the key
+    into ``render_context``. If you're keeping track of several state variables,
+    make ``render_context[self]`` a dictionary.
+
+Registering the tag
+~~~~~~~~~~~~~~~~~~~
+
+Finally, register the tag with your module's ``Library`` instance, as explained
+in "Writing custom template filters" above. Example::
+
+    register.tag('current_time', do_current_time)
+
+The ``tag()`` method takes two arguments:
+
+    1. The name of the template tag -- a string. If this is left out, the
+       name of the compilation function will be used.
+    2. The compilation function -- a Python function (not the name of the
+       function as a string).
+
+As with filter registration, it is also possible to use this as a decorator::
+
+    @register.tag(name="current_time")