      register.inclusion_tag('link.html', takes_context=True)(jump_link)
  
  (Note that the first parameter to the function *must* be called ``context``.)
  
  In that ``register.inclusion_tag()`` line, we specified ``takes_context=True``
  and the name of the template. Here's what the template ``link.html`` might look
  like:
  
  .. code-block:: html+django
  
      Jump directly to <a href="{{ link }}">{{ title }}</a>.
  
 
</s> remove (Note that the first parameter to the function *must* be called ``context``.)
 </s> add Although you can pass any number of arguments to a template tag using
``token.split_contents()``, the arguments are all unpacked as
string literals. A little more work is required in order to pass dynamic
content (a template variable) to a template tag as an argument. </s> remove     # The first argument *must* be called "context" here.
    def jump_link(context):
        return {
            'link': context['home_link'],
            'title': context['home_title'],
        }
    # Register the custom tag as an inclusion tag with takes_context=True.
    register.inclusion_tag('link.html', takes_context=True)(jump_link)
 </s> add Passing template variables to the tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ </s> remove     Jump directly to <a href="{{ link }}">{{ title }}</a>.
 </s> add     <p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p> </s> remove Tags are more complex than filters, because tags can do anything.
 </s> add Tags are more complex than filters, because tags can do anything. Django
provides a number of shortcuts that make writing most types of tags easier.
First we'll explore those shortcuts, then explain how to write a tag from
scratch for those cases when the shortcuts aren't powerful enough.

.. _howto-custom-template-tags-simple-tags:

Simple tags
~~~~~~~~~~~

.. method:: django.template.Library.simple_tag()

Many template tags take a number of arguments -- strings or template variables
-- and return a string after doing some processing based solely on
the input arguments and some external information. For example, a
``current_time`` tag might accept a format string and return the time as a
string formatted accordingly.

To ease the creation of these types of tags, Django provides a helper function,
``simple_tag``. This function, which is a method of
``django.template.Library``, takes a function that accepts any number of
arguments, wraps it in a ``render`` function and the other necessary bits
mentioned above and registers it with the template system.

Our ``current_time`` function could thus be written like this::

    import datetime
    from django import template

    register = template.Library()

    @register.simple_tag
    def current_time(format_string):
        return datetime.datetime.now().strftime(format_string)

A few things to note about the ``simple_tag`` helper function:

* Checking for the required number of arguments, etc., has already been
  done by the time our function is called, so we don't need to do that.
* The quotes around the argument (if any) have already been stripped away,
  so we just receive a plain string.
* If the argument was a template variable, our function is passed the
  current value of the variable, not the variable itself.

If your template tag needs to access the current context, you can use the
``takes_context`` argument when registering your tag::

    @register.simple_tag(takes_context=True)
    def current_time(context, format_string):
        timezone = context['timezone']
        return your_get_current_time_method(timezone, format_string)

Note that the first argument *must* be called ``context``.

For more information on how the ``takes_context`` option works, see the section
on :ref:`inclusion tags<howto-custom-template-tags-inclusion-tags>`.

If you need to rename your tag, you can provide a custom name for it::

    register.simple_tag(lambda x: x - 1, name='minusone')

    @register.simple_tag(name='minustwo')
    def some_function(value):
        return value - 2

``simple_tag`` functions may accept any number of positional or keyword
arguments. For example::

    @register.simple_tag
    def my_tag(a, b, *args, **kwargs):
        warning = kwargs['warning']
        profile = kwargs['profile']
        ...
        return ...

Then in the template any number of arguments, separated by spaces, may be
passed to the template tag. Like in Python, the values for keyword arguments
are set using the equal sign ("``=``") and must be provided after the
positional arguments. For example:

.. code-block:: html+django

    {% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

.. _howto-custom-template-tags-inclusion-tags:

Inclusion tags
~~~~~~~~~~~~~~

.. method:: django.template.Library.inclusion_tag()

Another common type of template tag is the type that displays some data by
rendering *another* template. For example, Django's admin interface uses custom
template tags to display the buttons along the bottom of the "add/change" form
pages. Those buttons always look the same, but the link targets change
depending on the object being edited -- so they're a perfect case for using a
small template that is filled with details from the current object. (In the
admin's case, this is the ``submit_row`` tag.)

These sorts of tags are called "inclusion tags".

Writing inclusion tags is probably best demonstrated by example. Let's write a
tag that outputs a list of choices for a given ``Poll`` object, such as was
created in the :ref:`tutorials <creating-models>`. We'll use the tag like this:

.. code-block:: html+django

    {% show_results poll %}

...and the output will be something like this:

.. code-block:: html

    <ul>
      <li>First choice</li>
      <li>Second choice</li>
      <li>Third choice</li>
    </ul>

First, define the function that takes the argument and produces a dictionary of
data for the result. The important point here is we only need to return a
dictionary, not anything more complex. This will be used as a template context
for the template fragment. Example::

    def show_results(poll):
        choices = poll.choice_set.all()
        return {'choices': choices}

Next, create the template used to render the tag's output. This template is a
fixed feature of the tag: the tag writer specifies it, not the template
designer. Following our example, the template is very simple:

.. code-block:: html+django

    <ul>
    {% for choice in choices %}
        <li> {{ choice }} </li>
    {% endfor %}
    </ul>

Now, create and register the inclusion tag by calling the ``inclusion_tag()``
method on a ``Library`` object. Following our example, if the above template is
in a file called ``results.html`` in a directory that's searched by the
template loader, we'd register the tag like this::

    # Here, register is a django.template.Library instance, as before
    @register.inclusion_tag('results.html')
    def show_results(poll):
        ...

Alternatively it is possible to register the inclusion tag using a
:class:`django.template.Template` instance::

    from django.template.loader import get_template
    t = get_template('results.html')
    register.inclusion_tag(t)(show_results)

...when first creating the function.

Sometimes, your inclusion tags might require a large number of arguments,
making it a pain for template authors to pass in all the arguments and remember
their order. To solve this, Django provides a ``takes_context`` option for
inclusion tags. If you specify ``takes_context`` in creating a template tag,
the tag will have no required arguments, and the underlying Python function
will have one argument -- the template context as of when the tag was called.

For example, say you're writing an inclusion tag that will always be used in a
context that contains ``home_link`` and ``home_title`` variables that point
back to the main page. Here's what the Python function would look like::

    @register.inclusion_tag('link.html', takes_context=True)
    def jump_link(context):
        return {
            'link': context['home_link'],
            'title': context['home_title'],
        }

Note that the first parameter to the function *must* be called ``context``.

In that ``register.inclusion_tag()`` line, we specified ``takes_context=True``
and the name of the template. Here's what the template ``link.html`` might look
like:

.. code-block:: html+django

    Jump directly to <a href="{{ link }}">{{ title }}</a>.

Then, any time you want to use that custom tag, load its library and call it
without any arguments, like so:

.. code-block:: html+django

    {% jump_link %}

Note that when you're using ``takes_context=True``, there's no need to pass
arguments to the template tag. It automatically gets access to the context.

The ``takes_context`` parameter defaults to ``False``. When it's set to
``True``, the tag is passed the context object, as in this example. That's the
only difference between this case and the previous ``inclusion_tag`` example.

``inclusion_tag`` functions may accept any number of positional or keyword
arguments. For example::

    @register.inclusion_tag('my_template.html')
    def my_tag(a, b, *args, **kwargs):
        warning = kwargs['warning']
        profile = kwargs['profile']
        ...
        return ...

Then in the template any number of arguments, separated by spaces, may be
passed to the template tag. Like in Python, the values for keyword arguments
are set using the equal sign ("``=``") and must be provided after the
positional arguments. For example:

.. code-block:: html+django

    {% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

.. _howto-custom-template-tags-assignment-tags:

Assignment tags
~~~~~~~~~~~~~~~

.. method:: django.template.Library.assignment_tag()

To ease the creation of tags setting a variable in the context, Django provides
a helper function, ``assignment_tag``. This function works the same way as
:ref:`simple_tag<howto-custom-template-tags-simple-tags>`, except that it
stores the tag's result in a specified context variable instead of directly
outputting it.

Our earlier ``current_time`` function could thus be written like this::

    @register.assignment_tag
    def get_current_time(format_string):
        return datetime.datetime.now().strftime(format_string)

You may then store the result in a template variable using the ``as`` argument
followed by the variable name, and output it yourself where you see fit:

.. code-block:: html+django

    {% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
    <p>The time is {{ the_time }}.</p>

If your template tag needs to access the current context, you can use the
``takes_context`` argument when registering your tag::

    @register.assignment_tag(takes_context=True)
    def get_current_time(context, format_string):
        timezone = context['timezone']
        return your_get_current_time_method(timezone, format_string)

Note that the first parameter to the function *must* be called ``context``.

For more information on how the ``takes_context`` option works, see the section
on :ref:`inclusion tags<howto-custom-template-tags-inclusion-tags>`.

``assignment_tag`` functions may accept any number of positional or keyword
arguments. For example::

    @register.assignment_tag
    def my_tag(a, b, *args, **kwargs):
        warning = kwargs['warning']
        profile = kwargs['profile']
        ...
        return ...

Then in the template any number of arguments, separated by spaces, may be
passed to the template tag. Like in Python, the values for keyword arguments
are set using the equal sign ("``=``") and must be provided after the
positional arguments. For example:

.. code-block:: html+django

    {% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile as the_result %}

Advanced custom template tags
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sometimes the basic features for custom template tag creation aren't enough.
Don't worry, Django gives you complete access to the internals required to build
a template tag from the ground up. </s> remove Then, any time you want to use that custom tag, load its library and call it
without any arguments, like so:
 </s> add Initially, ``token.split_contents()`` will return three values:
While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a
:class:`~django.db.models.DateTimeField` from an object and have the template
tag format that date-time:
      register.inclusion_tag('link.html', takes_context=True)(jump_link)
  
  (Note that the first parameter to the function *must* be called ``context``.)
  
While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a
:class:`~django.db.models.DateTimeField` from an object and have the template
tag format that date-time:
While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a
:class:`~django.db.models.DateTimeField` from an object and have the template
tag format that date-time:
While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a
:class:`~django.db.models.DateTimeField` from an object and have the template
tag format that date-time:
  
  .. code-block:: html+django
  
      Jump directly to <a href="{{ link }}">{{ title }}</a>.
  
keep keep keep keep replace replace replace keep keep keep keep keep
 Fixed #20435 -- Reordered the custom template tags docs.

Introduced the various shortcuts before explaining the more complex
parser/render functionality.

Also removed non-decorator syntax: it's been years since Django
supported a Python version without decorators. 
docs/howto/custom-template-tags.txt