PageRenderTime 35ms CodeModel.GetById 15ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 1ms

/docs/howto/custom-template-tags.txt

https://code.google.com/p/mango-py/
Plain Text | 949 lines | 711 code | 238 blank | 0 comment | 0 complexity | 8de3164fc384b791e25f8cf374f57c0d MD5 | raw file
  1================================
  2Custom template tags and filters
  3================================
  4
  5Introduction
  6============
  7
  8Django's template system comes with a wide variety of :doc:`built-in
  9tags and filters </ref/templates/builtins>` designed to address the
 10presentation logic needs of your application. Nevertheless, you may
 11find yourself needing functionality that is not covered by the core
 12set of template primitives. You can extend the template engine by
 13defining custom tags and filters using Python, and then make them
 14available to your templates using the ``{% load %}`` tag.
 15
 16Code layout
 17-----------
 18
 19Custom template tags and filters must live inside a Django app. If they relate
 20to an existing app it makes sense to bundle them there; otherwise, you should
 21create a new app to hold them.
 22
 23The app should contain a ``templatetags`` directory, at the same level as
 24``models.py``, ``views.py``, etc. If this doesn't already exist, create it -
 25don't forget the ``__init__.py`` file to ensure the directory is treated as a
 26Python package.
 27
 28Your custom tags and filters will live in a module inside the ``templatetags``
 29directory. The name of the module file is the name you'll use to load the tags
 30later, so be careful to pick a name that won't clash with custom tags and
 31filters in another app.
 32
 33For example, if your custom tags/filters are in a file called
 34``poll_extras.py``, your app layout might look like this::
 35
 36    polls/
 37        models.py
 38        templatetags/
 39            __init__.py
 40            poll_extras.py
 41        views.py
 42
 43And in your template you would use the following:
 44
 45.. code-block:: html+django
 46
 47    {% load poll_extras %}
 48
 49The app that contains the custom tags must be in :setting:`INSTALLED_APPS` in
 50order for the ``{% load %}`` tag to work. This is a security feature: It allows
 51you to host Python code for many template libraries on a single host machine
 52without enabling access to all of them for every Django installation.
 53
 54There's no limit on how many modules you put in the ``templatetags`` package.
 55Just keep in mind that a ``{% load %}`` statement will load tags/filters for
 56the given Python module name, not the name of the app.
 57
 58To be a valid tag library, the module must contain a module-level variable
 59named ``register`` that is a ``template.Library`` instance, in which all the
 60tags and filters are registered. So, near the top of your module, put the
 61following::
 62
 63    from django import template
 64
 65    register = template.Library()
 66
 67.. admonition:: Behind the scenes
 68
 69    For a ton of examples, read the source code for Django's default filters
 70    and tags. They're in ``django/template/defaultfilters.py`` and
 71    ``django/template/defaulttags.py``, respectively.
 72
 73Writing custom template filters
 74-------------------------------
 75
 76Custom filters are just Python functions that take one or two arguments:
 77
 78    * The value of the variable (input) -- not necessarily a string.
 79    * The value of the argument -- this can have a default value, or be left
 80      out altogether.
 81
 82For example, in the filter ``{{ var|foo:"bar" }}``, the filter ``foo`` would be
 83passed the variable ``var`` and the argument ``"bar"``.
 84
 85Filter functions should always return something. They shouldn't raise
 86exceptions. They should fail silently. In case of error, they should return
 87either the original input or an empty string -- whichever makes more sense.
 88
 89Here's an example filter definition::
 90
 91    def cut(value, arg):
 92        "Removes all values of arg from the given string"
 93        return value.replace(arg, '')
 94
 95And here's an example of how that filter would be used:
 96
 97.. code-block:: html+django
 98
 99    {{ somevariable|cut:"0" }}
100
101Most filters don't take arguments. In this case, just leave the argument out of
102your function. Example::
103
104    def lower(value): # Only one argument.
105        "Converts a string into all lowercase"
106        return value.lower()
107
108Template filters that expect strings
109~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110
111If you're writing a template filter that only expects a string as the first
112argument, you should use the decorator ``stringfilter``. This will
113convert an object to its string value before being passed to your function::
114
115    from django.template.defaultfilters import stringfilter
116
117    @stringfilter
118    def lower(value):
119        return value.lower()
120
121This way, you'll be able to pass, say, an integer to this filter, and it
122won't cause an ``AttributeError`` (because integers don't have ``lower()``
123methods).
124
125Registering custom filters
126~~~~~~~~~~~~~~~~~~~~~~~~~~
127
128Once you've written your filter definition, you need to register it with
129your ``Library`` instance, to make it available to Django's template language::
130
131    register.filter('cut', cut)
132    register.filter('lower', lower)
133
134The ``Library.filter()`` method takes two arguments:
135
136    1. The name of the filter -- a string.
137    2. The compilation function -- a Python function (not the name of the
138       function as a string).
139
140You can use ``register.filter()`` as a decorator instead::
141
142    @register.filter(name='cut')
143    @stringfilter
144    def cut(value, arg):
145        return value.replace(arg, '')
146
147    @register.filter
148    @stringfilter
149    def lower(value):
150        return value.lower()
151
152If you leave off the ``name`` argument, as in the second example above, Django
153will use the function's name as the filter name.
154
155Filters and auto-escaping
156~~~~~~~~~~~~~~~~~~~~~~~~~
157
158When writing a custom filter, give some thought to how the filter will interact
159with Django's auto-escaping behavior. Note that three types of strings can be
160passed around inside the template code:
161
162    * **Raw strings** are the native Python ``str`` or ``unicode`` types. On
163      output, they're escaped if auto-escaping is in effect and presented
164      unchanged, otherwise.
165
166    * **Safe strings** are strings that have been marked safe from further
167      escaping at output time. Any necessary escaping has already been done.
168      They're commonly used for output that contains raw HTML that is intended
169      to be interpreted as-is on the client side.
170
171      Internally, these strings are of type ``SafeString`` or ``SafeUnicode``.
172      They share a common base class of ``SafeData``, so you can test
173      for them using code like::
174
175          if isinstance(value, SafeData):
176              # Do something with the "safe" string.
177
178    * **Strings marked as "needing escaping"** are *always* escaped on
179      output, regardless of whether they are in an ``autoescape`` block or not.
180      These strings are only escaped once, however, even if auto-escaping
181      applies.
182
183      Internally, these strings are of type ``EscapeString`` or
184      ``EscapeUnicode``. Generally you don't have to worry about these; they
185      exist for the implementation of the ``escape`` filter.
186
187Template filter code falls into one of two situations:
188
189    1. Your filter does not introduce any HTML-unsafe characters (``<``, ``>``,
190       ``'``, ``"`` or ``&``) into the result that were not already present. In
191       this case, you can let Django take care of all the auto-escaping
192       handling for you. All you need to do is put the ``is_safe`` attribute on
193       your filter function and set it to ``True``, like so::
194
195           @register.filter
196           def myfilter(value):
197               return value
198           myfilter.is_safe = True
199
200       This attribute tells Django that if a "safe" string is passed into your
201       filter, the result will still be "safe" and if a non-safe string is
202       passed in, Django will automatically escape it, if necessary.
203
204       You can think of this as meaning "this filter is safe -- it doesn't
205       introduce any possibility of unsafe HTML."
206
207       The reason ``is_safe`` is necessary is because there are plenty of
208       normal string operations that will turn a ``SafeData`` object back into
209       a normal ``str`` or ``unicode`` object and, rather than try to catch
210       them all, which would be very difficult, Django repairs the damage after
211       the filter has completed.
212
213       For example, suppose you have a filter that adds the string ``xx`` to the
214       end of any input. Since this introduces no dangerous HTML characters to
215       the result (aside from any that were already present), you should mark
216       your filter with ``is_safe``::
217
218           @register.filter
219           def add_xx(value):
220               return '%sxx' % value
221           add_xx.is_safe = True
222
223       When this filter is used in a template where auto-escaping is enabled,
224       Django will escape the output whenever the input is not already marked as
225       "safe".
226
227       By default, ``is_safe`` defaults to ``False``, and you can omit it from
228       any filters where it isn't required.
229
230       Be careful when deciding if your filter really does leave safe strings
231       as safe. If you're *removing* characters, you might inadvertently leave
232       unbalanced HTML tags or entities in the result. For example, removing a
233       ``>`` from the input might turn ``<a>`` into ``<a``, which would need to
234       be escaped on output to avoid causing problems. Similarly, removing a
235       semicolon (``;``) can turn ``&amp;`` into ``&amp``, which is no longer a
236       valid entity and thus needs further escaping. Most cases won't be nearly
237       this tricky, but keep an eye out for any problems like that when
238       reviewing your code.
239
240       Marking a filter ``is_safe`` will coerce the filter's return value to
241       a string.  If your filter should return a boolean or other non-string
242       value, marking it ``is_safe`` will probably have unintended
243       consequences (such as converting a boolean False to the string
244       'False').
245
246    2. Alternatively, your filter code can manually take care of any necessary
247       escaping. This is necessary when you're introducing new HTML markup into
248       the result. You want to mark the output as safe from further
249       escaping so that your HTML markup isn't escaped further, so you'll need
250       to handle the input yourself.
251
252       To mark the output as a safe string, use
253       :func:`django.utils.safestring.mark_safe`.
254
255       Be careful, though. You need to do more than just mark the output as
256       safe. You need to ensure it really *is* safe, and what you do depends on
257       whether auto-escaping is in effect. The idea is to write filters than
258       can operate in templates where auto-escaping is either on or off in
259       order to make things easier for your template authors.
260
261       In order for your filter to know the current auto-escaping state, set
262       the ``needs_autoescape`` attribute to ``True`` on your function. (If you
263       don't specify this attribute, it defaults to ``False``). This attribute
264       tells Django that your filter function wants to be passed an extra
265       keyword argument, called ``autoescape``, that is ``True`` if
266       auto-escaping is in effect and ``False`` otherwise.
267
268       For example, let's write a filter that emphasizes the first character of
269       a string::
270
271           from django.utils.html import conditional_escape
272           from django.utils.safestring import mark_safe
273
274           def initial_letter_filter(text, autoescape=None):
275               first, other = text[0], text[1:]
276               if autoescape:
277                   esc = conditional_escape
278               else:
279                   esc = lambda x: x
280               result = '<strong>%s</strong>%s' % (esc(first), esc(other))
281               return mark_safe(result)
282           initial_letter_filter.needs_autoescape = True
283
284       The ``needs_autoescape`` attribute on the filter function and the
285       ``autoescape`` keyword argument mean that our function will know whether
286       automatic escaping is in effect when the filter is called. We use
287       ``autoescape`` to decide whether the input data needs to be passed
288       through ``django.utils.html.conditional_escape`` or not. (In the latter
289       case, we just use the identity function as the "escape" function.) The
290       ``conditional_escape()`` function is like ``escape()`` except it only
291       escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
292       instance is passed to ``conditional_escape()``, the data is returned
293       unchanged.
294
295       Finally, in the above example, we remember to mark the result as safe
296       so that our HTML is inserted directly into the template without further
297       escaping.
298
299       There's no need to worry about the ``is_safe`` attribute in this case
300       (although including it wouldn't hurt anything). Whenever you manually
301       handle the auto-escaping issues and return a safe string, the
302       ``is_safe`` attribute won't change anything either way.
303
304Writing custom template tags
305----------------------------
306
307Tags are more complex than filters, because tags can do anything.
308
309A quick overview
310~~~~~~~~~~~~~~~~
311
312Above, this document explained that the template system works in a two-step
313process: compiling and rendering. To define a custom template tag, you specify
314how the compilation works and how the rendering works.
315
316When Django compiles a template, it splits the raw template text into
317''nodes''. Each node is an instance of ``django.template.Node`` and has
318a ``render()`` method. A compiled template is, simply, a list of ``Node``
319objects. When you call ``render()`` on a compiled template object, the template
320calls ``render()`` on each ``Node`` in its node list, with the given context.
321The results are all concatenated together to form the output of the template.
322
323Thus, to define a custom template tag, you specify how the raw template tag is
324converted into a ``Node`` (the compilation function), and what the node's
325``render()`` method does.
326
327Writing the compilation function
328~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
329
330For each template tag the template parser encounters, it calls a Python
331function with the tag contents and the parser object itself. This function is
332responsible for returning a ``Node`` instance based on the contents of the tag.
333
334For example, let's write a template tag, ``{% current_time %}``, that displays
335the current date/time, formatted according to a parameter given in the tag, in
336`strftime syntax`_. It's a good idea to decide the tag syntax before anything
337else. In our case, let's say the tag should be used like this:
338
339.. code-block:: html+django
340
341    <p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
342
343.. _`strftime syntax`: http://docs.python.org/library/time.html#time.strftime
344
345The parser for this function should grab the parameter and create a ``Node``
346object::
347
348    from django import template
349    def do_current_time(parser, token):
350        try:
351            # split_contents() knows not to split quoted strings.
352            tag_name, format_string = token.split_contents()
353        except ValueError:
354            raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0])
355        if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
356            raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name)
357        return CurrentTimeNode(format_string[1:-1])
358
359Notes:
360
361    * ``parser`` is the template parser object. We don't need it in this
362      example.
363
364    * ``token.contents`` is a string of the raw contents of the tag. In our
365      example, it's ``'current_time "%Y-%m-%d %I:%M %p"'``.
366
367    * The ``token.split_contents()`` method separates the arguments on spaces
368      while keeping quoted strings together. The more straightforward
369      ``token.contents.split()`` wouldn't be as robust, as it would naively
370      split on *all* spaces, including those within quoted strings. It's a good
371      idea to always use ``token.split_contents()``.
372
373    * This function is responsible for raising
374      ``django.template.TemplateSyntaxError``, with helpful messages, for
375      any syntax error.
376
377    * The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable.
378      Don't hard-code the tag's name in your error messages, because that
379      couples the tag's name to your function. ``token.contents.split()[0]``
380      will ''always'' be the name of your tag -- even when the tag has no
381      arguments.
382
383    * The function returns a ``CurrentTimeNode`` with everything the node needs
384      to know about this tag. In this case, it just passes the argument --
385      ``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the
386      template tag are removed in ``format_string[1:-1]``.
387
388    * The parsing is very low-level. The Django developers have experimented
389      with writing small frameworks on top of this parsing system, using
390      techniques such as EBNF grammars, but those experiments made the template
391      engine too slow. It's low-level because that's fastest.
392
393Writing the renderer
394~~~~~~~~~~~~~~~~~~~~
395
396The second step in writing custom tags is to define a ``Node`` subclass that
397has a ``render()`` method.
398
399Continuing the above example, we need to define ``CurrentTimeNode``::
400
401    from django import template
402    import datetime
403    class CurrentTimeNode(template.Node):
404        def __init__(self, format_string):
405            self.format_string = format_string
406        def render(self, context):
407            return datetime.datetime.now().strftime(self.format_string)
408
409Notes:
410
411    * ``__init__()`` gets the ``format_string`` from ``do_current_time()``.
412      Always pass any options/parameters/arguments to a ``Node`` via its
413      ``__init__()``.
414
415    * The ``render()`` method is where the work actually happens.
416
417    * ``render()`` should never raise ``TemplateSyntaxError`` or any other
418      exception. It should fail silently, just as template filters should.
419
420Ultimately, this decoupling of compilation and rendering results in an
421efficient template system, because a template can render multiple contexts
422without having to be parsed multiple times.
423
424Auto-escaping considerations
425~~~~~~~~~~~~~~~~~~~~~~~~~~~~
426
427The output from template tags is **not** automatically run through the
428auto-escaping filters. However, there are still a couple of things you should
429keep in mind when writing a template tag.
430
431If the ``render()`` function of your template stores the result in a context
432variable (rather than returning the result in a string), it should take care
433to call ``mark_safe()`` if appropriate. When the variable is ultimately
434rendered, it will be affected by the auto-escape setting in effect at the
435time, so content that should be safe from further escaping needs to be marked
436as such.
437
438Also, if your template tag creates a new context for performing some
439sub-rendering, set the auto-escape attribute to the current context's value.
440The ``__init__`` method for the ``Context`` class takes a parameter called
441``autoescape`` that you can use for this purpose. For example::
442
443    def render(self, context):
444        # ...
445        new_context = Context({'var': obj}, autoescape=context.autoescape)
446        # ... Do something with new_context ...
447
448This is not a very common situation, but it's useful if you're rendering a
449template yourself. For example::
450
451    def render(self, context):
452        t = template.loader.get_template('small_fragment.html')
453        return t.render(Context({'var': obj}, autoescape=context.autoescape))
454
455If we had neglected to pass in the current ``context.autoescape`` value to our
456new ``Context`` in this example, the results would have *always* been
457automatically escaped, which may not be the desired behavior if the template
458tag is used inside a ``{% autoescape off %}`` block.
459
460.. _template_tag_thread_safety:
461
462Thread-safety considerations
463~~~~~~~~~~~~~~~~~~~~~~~~~~~~
464
465.. versionadded:: 1.2
466
467Once a node is parsed, its ``render`` method may be called any number of times.
468Since Django is sometimes run in multi-threaded environments, a single node may
469be simultaneously rendering with different contexts in response to two separate
470requests. Therefore, it's important to make sure your template tags are thread
471safe.
472
473To make sure your template tags are thread safe, you should never store state
474information on the node itself. For example, Django provides a builtin ``cycle``
475template tag that cycles among a list of given strings each time it's rendered::
476
477    {% for o in some_list %}
478        <tr class="{% cycle 'row1' 'row2' %}>
479            ...
480        </tr>
481    {% endfor %}
482
483A naive implementation of ``CycleNode`` might look something like this::
484
485    class CycleNode(Node):
486        def __init__(self, cyclevars):
487            self.cycle_iter = itertools.cycle(cyclevars)
488        def render(self, context):
489            return self.cycle_iter.next()
490
491But, suppose we have two templates rendering the template snippet from above at
492the same time:
493
494    1. Thread 1 performs its first loop iteration, ``CycleNode.render()``
495       returns 'row1'
496    2. Thread 2 performs its first loop iteration, ``CycleNode.render()``
497       returns 'row2'
498    3. Thread 1 performs its second loop iteration, ``CycleNode.render()``
499       returns 'row1'
500    4. Thread 2 performs its second loop iteration, ``CycleNode.render()``
501       returns 'row2'
502
503The CycleNode is iterating, but it's iterating globally. As far as Thread 1
504and Thread 2 are concerned, it's always returning the same value. This is
505obviously not what we want!
506
507To address this problem, Django provides a ``render_context`` that's associated
508with the ``context`` of the template that is currently being rendered. The
509``render_context`` behaves like a Python dictionary, and should be used to store
510``Node`` state between invocations of the ``render`` method.
511
512Let's refactor our ``CycleNode`` implementation to use the ``render_context``::
513
514    class CycleNode(Node):
515        def __init__(self, cyclevars):
516            self.cyclevars = cyclevars
517        def render(self, context):
518            if self not in context.render_context:
519                context.render_context[self] = itertools.cycle(self.cyclevars)
520            cycle_iter = context.render_context[self]
521            return cycle_iter.next()
522
523Note that it's perfectly safe to store global information that will not change
524throughout the life of the ``Node`` as an attribute. In the case of
525``CycleNode``, the ``cyclevars`` argument doesn't change after the ``Node`` is
526instantiated, so we don't need to put it in the ``render_context``. But state
527information that is specific to the template that is currently being rendered,
528like the current iteration of the ``CycleNode``, should be stored in the
529``render_context``.
530
531.. note::
532    Notice how we used ``self`` to scope the ``CycleNode`` specific information
533    within the ``render_context``. There may be multiple ``CycleNodes`` in a
534    given template, so we need to be careful not to clobber another node's state
535    information. The easiest way to do this is to always use ``self`` as the key
536    into ``render_context``. If you're keeping track of several state variables,
537    make ``render_context[self]`` a dictionary.
538
539Registering the tag
540~~~~~~~~~~~~~~~~~~~
541
542Finally, register the tag with your module's ``Library`` instance, as explained
543in "Writing custom template filters" above. Example::
544
545    register.tag('current_time', do_current_time)
546
547The ``tag()`` method takes two arguments:
548
549    1. The name of the template tag -- a string. If this is left out, the
550       name of the compilation function will be used.
551    2. The compilation function -- a Python function (not the name of the
552       function as a string).
553
554As with filter registration, it is also possible to use this as a decorator::
555
556    @register.tag(name="current_time")
557    def do_current_time(parser, token):
558        # ...
559
560    @register.tag
561    def shout(parser, token):
562        # ...
563
564If you leave off the ``name`` argument, as in the second example above, Django
565will use the function's name as the tag name.
566
567Passing template variables to the tag
568~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
569
570Although you can pass any number of arguments to a template tag using
571``token.split_contents()``, the arguments are all unpacked as
572string literals. A little more work is required in order to pass dynamic
573content (a template variable) to a template tag as an argument.
574
575While the previous examples have formatted the current time into a string and
576returned the string, suppose you wanted to pass in a ``DateTimeField`` from an
577object and have the template tag format that date-time:
578
579.. code-block:: html+django
580
581    <p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p>
582
583Initially, ``token.split_contents()`` will return three values:
584
585    1. The tag name ``format_time``.
586    2. The string "blog_entry.date_updated" (without the surrounding quotes).
587    3. The formatting string "%Y-%m-%d %I:%M %p". The return value from
588       ``split_contents()`` will include the leading and trailing quotes for
589       string literals like this.
590
591Now your tag should begin to look like this::
592
593    from django import template
594    def do_format_time(parser, token):
595        try:
596            # split_contents() knows not to split quoted strings.
597            tag_name, date_to_be_formatted, format_string = token.split_contents()
598        except ValueError:
599            raise template.TemplateSyntaxError("%r tag requires exactly two arguments" % token.contents.split()[0])
600        if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
601            raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name)
602        return FormatTimeNode(date_to_be_formatted, format_string[1:-1])
603
604You also have to change the renderer to retrieve the actual contents of the
605``date_updated`` property of the ``blog_entry`` object.  This can be
606accomplished by using the ``Variable()`` class in ``django.template``.
607
608To use the ``Variable`` class, simply instantiate it with the name of the
609variable to be resolved, and then call ``variable.resolve(context)``. So,
610for example::
611
612    class FormatTimeNode(template.Node):
613        def __init__(self, date_to_be_formatted, format_string):
614            self.date_to_be_formatted = template.Variable(date_to_be_formatted)
615            self.format_string = format_string
616
617        def render(self, context):
618            try:
619                actual_date = self.date_to_be_formatted.resolve(context)
620                return actual_date.strftime(self.format_string)
621            except template.VariableDoesNotExist:
622                return ''
623
624Variable resolution will throw a ``VariableDoesNotExist`` exception if it cannot
625resolve the string passed to it in the current context of the page.
626
627Shortcut for simple tags
628~~~~~~~~~~~~~~~~~~~~~~~~
629
630Many template tags take a number of arguments -- strings or template variables
631-- and return a string after doing some processing based solely on
632the input arguments and some external information. For example, the
633``current_time`` tag we wrote above is of this variety: we give it a format
634string, it returns the time as a string.
635
636To ease the creation of these types of tags, Django provides a helper function,
637``simple_tag``. This function, which is a method of
638``django.template.Library``, takes a function that accepts any number of
639arguments, wraps it in a ``render`` function and the other necessary bits
640mentioned above and registers it with the template system.
641
642Our earlier ``current_time`` function could thus be written like this::
643
644    def current_time(format_string):
645        return datetime.datetime.now().strftime(format_string)
646
647    register.simple_tag(current_time)
648
649The decorator syntax also works::
650
651    @register.simple_tag
652    def current_time(format_string):
653        ...
654
655A couple of things to note about the ``simple_tag`` helper function:
656
657    * Checking for the required number of arguments, etc., has already been
658      done by the time our function is called, so we don't need to do that.
659    * The quotes around the argument (if any) have already been stripped away,
660      so we just receive a plain string.
661    * If the argument was a template variable, our function is passed the
662      current value of the variable, not the variable itself.
663
664.. versionadded:: 1.3
665
666If your template tag needs to access the current context, you can use the
667``takes_context`` argument when registering your tag::
668
669    # The first argument *must* be called "context" here.
670    def current_time(context, format_string):
671        timezone = context['timezone']
672        return your_get_current_time_method(timezone, format_string)
673
674    register.simple_tag(takes_context=True)(current_time)
675
676Or, using decorator syntax::
677
678    @register.simple_tag(takes_context=True)
679    def current_time(context, format_string):
680        timezone = context['timezone']
681        return your_get_current_time_method(timezone, format_string)
682
683For more information on how the ``takes_context`` option works, see the section
684on `inclusion tags`_.
685
686.. _howto-custom-template-tags-inclusion-tags:
687
688Inclusion tags
689~~~~~~~~~~~~~~
690
691Another common type of template tag is the type that displays some data by
692rendering *another* template. For example, Django's admin interface uses custom
693template tags to display the buttons along the bottom of the "add/change" form
694pages. Those buttons always look the same, but the link targets change depending
695on the object being edited -- so they're a perfect case for using a small
696template that is filled with details from the current object. (In the admin's
697case, this is the ``submit_row`` tag.)
698
699These sorts of tags are called "inclusion tags".
700
701Writing inclusion tags is probably best demonstrated by example. Let's write a
702tag that outputs a list of choices for a given ``Poll`` object, such as was
703created in the :ref:`tutorials <creating-models>`. We'll use the tag like this:
704
705.. code-block:: html+django
706
707    {% show_results poll %}
708
709...and the output will be something like this:
710
711.. code-block:: html
712
713    <ul>
714      <li>First choice</li>
715      <li>Second choice</li>
716      <li>Third choice</li>
717    </ul>
718
719First, define the function that takes the argument and produces a dictionary of
720data for the result. The important point here is we only need to return a
721dictionary, not anything more complex. This will be used as a template context
722for the template fragment. Example::
723
724    def show_results(poll):
725        choices = poll.choice_set.all()
726        return {'choices': choices}
727
728Next, create the template used to render the tag's output. This template is a
729fixed feature of the tag: the tag writer specifies it, not the template
730designer. Following our example, the template is very simple:
731
732.. code-block:: html+django
733
734    <ul>
735    {% for choice in choices %}
736        <li> {{ choice }} </li>
737    {% endfor %}
738    </ul>
739
740Now, create and register the inclusion tag by calling the ``inclusion_tag()``
741method on a ``Library`` object. Following our example, if the above template is
742in a file called ``results.html`` in a directory that's searched by the template
743loader, we'd register the tag like this::
744
745    # Here, register is a django.template.Library instance, as before
746    register.inclusion_tag('results.html')(show_results)
747
748As always, decorator syntax works as well, so we could have written::
749
750    @register.inclusion_tag('results.html')
751    def show_results(poll):
752        ...
753
754...when first creating the function.
755
756Sometimes, your inclusion tags might require a large number of arguments,
757making it a pain for template authors to pass in all the arguments and remember
758their order. To solve this, Django provides a ``takes_context`` option for
759inclusion tags. If you specify ``takes_context`` in creating a template tag,
760the tag will have no required arguments, and the underlying Python function
761will have one argument -- the template context as of when the tag was called.
762
763For example, say you're writing an inclusion tag that will always be used in a
764context that contains ``home_link`` and ``home_title`` variables that point
765back to the main page. Here's what the Python function would look like::
766
767    # The first argument *must* be called "context" here.
768    def jump_link(context):
769        return {
770            'link': context['home_link'],
771            'title': context['home_title'],
772        }
773    # Register the custom tag as an inclusion tag with takes_context=True.
774    register.inclusion_tag('link.html', takes_context=True)(jump_link)
775
776(Note that the first parameter to the function *must* be called ``context``.)
777
778In that ``register.inclusion_tag()`` line, we specified ``takes_context=True``
779and the name of the template. Here's what the template ``link.html`` might look
780like:
781
782.. code-block:: html+django
783
784    Jump directly to <a href="{{ link }}">{{ title }}</a>.
785
786Then, any time you want to use that custom tag, load its library and call it
787without any arguments, like so:
788
789.. code-block:: html+django
790
791    {% jump_link %}
792
793Note that when you're using ``takes_context=True``, there's no need to pass
794arguments to the template tag. It automatically gets access to the context.
795
796The ``takes_context`` parameter defaults to ``False``. When it's set to *True*,
797the tag is passed the context object, as in this example. That's the only
798difference between this case and the previous ``inclusion_tag`` example.
799
800Setting a variable in the context
801~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
802
803The above examples simply output a value. Generally, it's more flexible if your
804template tags set template variables instead of outputting values. That way,
805template authors can reuse the values that your template tags create.
806
807To set a variable in the context, just use dictionary assignment on the context
808object in the ``render()`` method. Here's an updated version of
809``CurrentTimeNode`` that sets a template variable ``current_time`` instead of
810outputting it::
811
812    class CurrentTimeNode2(template.Node):
813        def __init__(self, format_string):
814            self.format_string = format_string
815        def render(self, context):
816            context['current_time'] = datetime.datetime.now().strftime(self.format_string)
817            return ''
818
819Note that ``render()`` returns the empty string. ``render()`` should always
820return string output. If all the template tag does is set a variable,
821``render()`` should return the empty string.
822
823Here's how you'd use this new version of the tag:
824
825.. code-block:: html+django
826
827    {% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p>
828
829.. admonition:: Variable scope in context
830
831    Any variable set in the context will only be available in the same ``block``
832    of the template in which it was assigned. This behavior is intentional;
833    it provides a scope for variables so that they don't conflict with
834    context in other blocks.
835
836But, there's a problem with ``CurrentTimeNode2``: The variable name
837``current_time`` is hard-coded. This means you'll need to make sure your
838template doesn't use ``{{ current_time }}`` anywhere else, because the
839``{% current_time %}`` will blindly overwrite that variable's value. A cleaner
840solution is to make the template tag specify the name of the output variable,
841like so:
842
843.. code-block:: html+django
844
845    {% current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
846    <p>The current time is {{ my_current_time }}.</p>
847
848To do that, you'll need to refactor both the compilation function and ``Node``
849class, like so::
850
851    class CurrentTimeNode3(template.Node):
852        def __init__(self, format_string, var_name):
853            self.format_string = format_string
854            self.var_name = var_name
855        def render(self, context):
856            context[self.var_name] = datetime.datetime.now().strftime(self.format_string)
857            return ''
858
859    import re
860    def do_current_time(parser, token):
861        # This version uses a regular expression to parse tag contents.
862        try:
863            # Splitting by None == splitting by spaces.
864            tag_name, arg = token.contents.split(None, 1)
865        except ValueError:
866            raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
867        m = re.search(r'(.*?) as (\w+)', arg)
868        if not m:
869            raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name)
870        format_string, var_name = m.groups()
871        if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
872            raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name)
873        return CurrentTimeNode3(format_string[1:-1], var_name)
874
875The difference here is that ``do_current_time()`` grabs the format string and
876the variable name, passing both to ``CurrentTimeNode3``.
877
878Parsing until another block tag
879~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
880
881Template tags can work in tandem. For instance, the standard ``{% comment %}``
882tag hides everything until ``{% endcomment %}``. To create a template tag such
883as this, use ``parser.parse()`` in your compilation function.
884
885Here's how the standard ``{% comment %}`` tag is implemented::
886
887    def do_comment(parser, token):
888        nodelist = parser.parse(('endcomment',))
889        parser.delete_first_token()
890        return CommentNode()
891
892    class CommentNode(template.Node):
893        def render(self, context):
894            return ''
895
896``parser.parse()`` takes a tuple of names of block tags ''to parse until''. It
897returns an instance of ``django.template.NodeList``, which is a list of
898all ``Node`` objects that the parser encountered ''before'' it encountered
899any of the tags named in the tuple.
900
901In ``"nodelist = parser.parse(('endcomment',))"`` in the above example,
902``nodelist`` is a list of all nodes between the ``{% comment %}`` and
903``{% endcomment %}``, not counting ``{% comment %}`` and ``{% endcomment %}``
904themselves.
905
906After ``parser.parse()`` is called, the parser hasn't yet "consumed" the
907``{% endcomment %}`` tag, so the code needs to explicitly call
908``parser.delete_first_token()``.
909
910``CommentNode.render()`` simply returns an empty string. Anything between
911``{% comment %}`` and ``{% endcomment %}`` is ignored.
912
913Parsing until another block tag, and saving contents
914~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
915
916In the previous example, ``do_comment()`` discarded everything between
917``{% comment %}`` and ``{% endcomment %}``. Instead of doing that, it's
918possible to do something with the code between block tags.
919
920For example, here's a custom template tag, ``{% upper %}``, that capitalizes
921everything between itself and ``{% endupper %}``.
922
923Usage:
924
925.. code-block:: html+django
926
927    {% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %}
928
929As in the previous example, we'll use ``parser.parse()``. But this time, we
930pass the resulting ``nodelist`` to the ``Node``::
931
932    def do_upper(parser, token):
933        nodelist = parser.parse(('endupper',))
934        parser.delete_first_token()
935        return UpperNode(nodelist)
936
937    class UpperNode(template.Node):
938        def __init__(self, nodelist):
939            self.nodelist = nodelist
940        def render(self, context):
941            output = self.nodelist.render(context)
942            return output.upper()
943
944The only new concept here is the ``self.nodelist.render(context)`` in
945``UpperNode.render()``.
946
947For more examples of complex rendering, see the source code for ``{% if %}``,
948``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
949``django/template/defaulttags.py``.