Made some edits to docs/templates_python.txt 'inclusion_tag' section

git-svn-id: http://code.djangoproject.com/svn/django/trunk@2979 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-05-25 05:29:27 +00:00
parent b631a50250
commit 14392b032d
1 changed files with 50 additions and 65 deletions

View File

@ -784,27 +784,23 @@ In Python 2.4, the decorator syntax also works::
Inclusion tags Inclusion tags
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Another type of template tag that is sometimes useful is when you want to Another common type of template tag is the type that displays some data by
display some data that is computed at render time in a template fragment. For rendering *another* template. For example, Django's admin interface uses custom
example, in Django's admin interface, there is a line of buttons along the template tags to display the buttons along the botton of the "add/change" form
bottom of the `create/edit record` screen. These buttons always look the same, pages. Those buttons always look the same, but the link targets change depending
but the link targets change depending upon the object being edited. So they on the object being edited -- so they're a perfect case for using a small
are a perfect example for using a small template that is filled in with template that is filled with details from the current object. (In the admin's
details from the current object. To save typing, it would also be nice if we case, this is the ``submit_row`` tag.)
could wrap this whole display up in a single tag (in the admin templates this
is the ``submit_row`` tag).
We call these sorts of tags `inclusion tags`. In your template, you pass in These sorts of tags are called `inclusion tags`.
any appropriate arguments and the tag uses those arguments, together with the
current context to render a template and include the result in the output.
Writing inclusion tags is probably best demonstrated by example. We will write Writing inclusion tags is probably best demonstrated by example. Let's write a
a tag that outputs a list of choices for a Poll object, such as was created in tag that outputs a list of choices for a given ``Poll`` object, such as was
the tutorials_. We will use this tag like this:: created in the tutorials_. We'll use the tag like this::
{% show_results poll %} {% show_results poll %}
and the output will be something like this:: ...and the output will be something like this::
<ul> <ul>
<li>First choice</li> <li>First choice</li>
@ -812,21 +808,18 @@ and the output will be something like this::
<li>Third choice</li> <li>Third choice</li>
</ul> </ul>
First, we define the function which takes the argument and produces a First, define the function that takes the argument and produces a dictionary of
dictionary of data for the result. The important point here is we only need to data for the result. The important point here is we only need to return a
return a dictionary, not anything more complex. This will be used to substitue dictionary, not anything more complex. This will be used as a template context
for values in the template fragment, just as when templates are used for the template fragment. Example::
elsewhere.
::
def show_results(poll): def show_results(poll):
choices = poll.choice_set.all() choices = poll.choice_set.all()
return {'choices': choices} return {'choices': choices}
We also need to create the template that is used to render the output. This Next, create the template used to render the tag's output. This template is a
template is a fixed feature of the tag: the tag writer specifies it, not the fixed feature of the tag: the tag writer specifies it, not the template
template designer. In our case, the template is very simple:: designer. Following our example, the template is very simple::
<ul> <ul>
{% for choice in choices %} {% for choice in choices %}
@ -834,50 +827,33 @@ template designer. In our case, the template is very simple::
{% endfor %} {% endfor %}
</ul> </ul>
Now we can create the inclusion tag. Suppose the above template is in a file Now, create and register the inclusion tag by calling the ``inclusion_tag()``
called ``results.html`` in a directory that is searched by the template method on a ``Library`` object. Following our example, if the above template is
loader. We register our new tag similarly to a normal tag. 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 # Here, register is a django.template.Library instance, as before
register.inclusion_tag('results.html')(show_results) register.inclusion_tag('results.html')(show_results)
As always, Python 2.4 decorator syntax works as well, so we could have As always, Python 2.4 decorator syntax works as well, so we could have
written written::
::
@inclusion_tag('results.html') @inclusion_tag('results.html')
def show_results(poll): def show_results(poll):
... ...
when first creating the function. ...when first creating the function.
In some cases, an inclusion tag might require a large number of arguments to Sometimes, your inclusion tags might require a large number of arguments,
display itself properly. In essence, it would depend largely on the current making it a pain for template authors to pass in all the arguments and remember
context it was being rendered with. We can make these sorts of tags easier to their order. To solve this, Django provides a ``takes_context`` option for
write by telling the ``inclusion_tag`` function that the whole context inclusion tags. If you specify ``takes_context`` in creating a template tag,
should be passed in as an argument to the function. This will be done the tag will have no required arguments, and the underlying Python function
invisibly as far as the template tag user is concerned: they will not need to will have one argument -- the template context as of when the tag was called.
do anything to pass in the context.
For example, suppose we are writing an inclusion tag that will always be used For example, say you're writing an inclusion tag that will always be used in a
in a context that contains ``home_link`` and ``home_title`` variables that context that contains ``home_link`` and ``home_title`` variables that point
point back to the main page. We can write a tag that is used like this:: back to the main page. Here's what the Python function would look like::
{% jump_link %}
and renders this::
Jump directly to <a href="http://example.com/home">Home</a>
The tag function is almost as simple as before. This time it takes no
arguments except the ``context`` (and the parameter `must` be called
``context`` in this case; the special parameter named is used internally by
Django to fill in the values correctly).
::
# The first argument *must* be called "context" here. # The first argument *must* be called "context" here.
def jump_link(context): def jump_link(context):
@ -885,19 +861,28 @@ Django to fill in the values correctly).
'link': context['home_link'], 'link': context['home_link'],
'title': context['home_title'], '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)
Our template is very simple again:: (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::
Jump directly to <a href="{{ link }}">{{ title }}</a>. Jump directly to <a href="{{ link }}">{{ title }}</a>.
Assuming the template is in a file called ``link.html``, we register this new Then, any time you want to use that custom tag, load its library and call it
tag as follows:: without any arguments, like so::
register.inclusion_tag('link.html', takes_context = True)(jump_link) {% jump_link %}
The ``takes_context`` parameter here defaults to *False*. When it is set to Note that when you're using ``takes_context=True``, there's no need to pass
*True*, our tag is passed the implicit context as in this example. That is the arguments to the template tag. It automatically gets access to the context.
only difference between this case and our previous use of ``inclusion_tag``.
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.
.. _tutorials: http://www.djangoproject.com/documentation/tutorial1/#creating-models .. _tutorials: http://www.djangoproject.com/documentation/tutorial1/#creating-models