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.
This commit is contained in:
parent
fc36437434
commit
524e71c9c2
|
@ -372,7 +372,291 @@ conversions in templates <time-zones-in-templates>`.
|
||||||
Writing custom template tags
|
Writing custom template tags
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Tags are more complex than filters, because tags can do anything.
|
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.
|
||||||
|
|
||||||
A quick overview
|
A quick overview
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
@ -399,10 +683,11 @@ 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
|
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.
|
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
|
For example, let's write a full implementation of our simple template tag,
|
||||||
the current date/time, formatted according to a parameter given in the tag, in
|
``{% current_time %}``, that displays the current date/time, formatted according
|
||||||
:func:`~time.strftime` syntax. It's a good idea to decide the tag syntax before
|
to a parameter given in the tag, in :func:`~time.strftime` syntax. It's a good
|
||||||
anything else. In our case, let's say the tag should be used like this:
|
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
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
@ -708,239 +993,6 @@ for example::
|
||||||
Variable resolution will throw a ``VariableDoesNotExist`` exception if it
|
Variable resolution will throw a ``VariableDoesNotExist`` exception if it
|
||||||
cannot resolve the string passed to it in the current context of the page.
|
cannot resolve the string passed to it in the current context of the page.
|
||||||
|
|
||||||
.. _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, the
|
|
||||||
``current_time`` tag we wrote above is of this variety: we give it a format
|
|
||||||
string, it returns the time as a string.
|
|
||||||
|
|
||||||
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 earlier ``current_time`` function could thus be written like this::
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
from django import template
|
|
||||||
|
|
||||||
register = template.Library()
|
|
||||||
|
|
||||||
def current_time(format_string):
|
|
||||||
return datetime.datetime.now().strftime(format_string)
|
|
||||||
|
|
||||||
register.simple_tag(current_time)
|
|
||||||
|
|
||||||
The decorator syntax also works::
|
|
||||||
|
|
||||||
@register.simple_tag
|
|
||||||
def current_time(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::
|
|
||||||
|
|
||||||
# The first argument *must* be called "context" here.
|
|
||||||
def current_time(context, format_string):
|
|
||||||
timezone = context['timezone']
|
|
||||||
return your_get_current_time_method(timezone, format_string)
|
|
||||||
|
|
||||||
register.simple_tag(takes_context=True)(current_time)
|
|
||||||
|
|
||||||
Or, using decorator syntax::
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
|
||||||
def current_time(context, format_string):
|
|
||||||
timezone = context['timezone']
|
|
||||||
return your_get_current_time_method(timezone, format_string)
|
|
||||||
|
|
||||||
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
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
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')(show_results)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
As always, decorator syntax works as well, so we could have written::
|
|
||||||
|
|
||||||
@register.inclusion_tag('results.html')
|
|
||||||
def show_results(poll):
|
|
||||||
...
|
|
||||||
|
|
||||||
...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::
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
(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 %}
|
|
||||||
|
|
||||||
Setting a variable in the context
|
Setting a variable in the context
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -1024,79 +1076,10 @@ The difference here is that ``do_current_time()`` grabs the format string and
|
||||||
the variable name, passing both to ``CurrentTimeNode3``.
|
the variable name, passing both to ``CurrentTimeNode3``.
|
||||||
|
|
||||||
Finally, if you only need to have a simple syntax for your custom
|
Finally, if you only need to have a simple syntax for your custom
|
||||||
context-updating template tag, you might want to consider using an
|
context-updating template tag, you might want to consider using the
|
||||||
:ref:`assignment tag <howto-custom-template-tags-assignment-tags>`.
|
:ref:`assignment tag <howto-custom-template-tags-assignment-tags>` shortcut
|
||||||
|
we introduced above.
|
||||||
|
|
||||||
.. _howto-custom-template-tags-assignment-tags:
|
|
||||||
|
|
||||||
Assignment tags
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
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::
|
|
||||||
|
|
||||||
def get_current_time(format_string):
|
|
||||||
return datetime.datetime.now().strftime(format_string)
|
|
||||||
|
|
||||||
register.assignment_tag(get_current_time)
|
|
||||||
|
|
||||||
The decorator syntax also works::
|
|
||||||
|
|
||||||
@register.assignment_tag
|
|
||||||
def get_current_time(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::
|
|
||||||
|
|
||||||
# The first argument *must* be called "context" here.
|
|
||||||
def get_current_time(context, format_string):
|
|
||||||
timezone = context['timezone']
|
|
||||||
return your_get_current_time_method(timezone, format_string)
|
|
||||||
|
|
||||||
register.assignment_tag(takes_context=True)(get_current_time)
|
|
||||||
|
|
||||||
Or, using decorator syntax::
|
|
||||||
|
|
||||||
@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)
|
|
||||||
|
|
||||||
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 %}
|
|
||||||
|
|
||||||
Parsing until another block tag
|
Parsing until another block tag
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
Loading…
Reference in New Issue