Django

Code

root/django/branches/0.90-bugfixes/docs/templates_python.txt

Revision 1261, 29.4 kB (checked in by adrian, 3 years ago)

Added links to auth docs in docs/templates_python.txt

Line 
1 ====================================================
2 The Django template language: For Python programmers
3 ====================================================
4
5 This document explains the Django template system from a technical
6 perspective -- how it works and how to extend it. If you're just looking for
7 reference on the language syntax, see
8 `The Django template language: For template authors`_.
9
10 .. _`The Django template language: For template authors`: http://www.djangoproject.com/documentation/templates/
11
12 Basics
13 ======
14
15 A **template** is a text document, or a normal Python string, that is marked-up
16 using the Django template language. A template can contain **block tags** or
17 **variables**.
18
19 A **block tag** is a symbol within a template that does something.
20
21 This definition is deliberately vague. For example, a block tag can output
22 content, serve as a control structure (an "if" statement or "for" loop), grab
23 content from a database or enable access to other template tags.
24
25 Block tags are surrounded by ``"{%"`` and ``"%}"``.
26
27 Example template with block tags::
28
29     {% if is_logged_in %}Thanks for logging in!{% else %}Please log in.{% endif %}
30
31 A **variable** is a symbol within a template that outputs a value.
32
33 Variable tags are surrounded by ``"{{"`` and ``"}}"``.
34
35 Example template with variables::
36
37     My first name is {{ first_name }}. My last name is {{ last_name }}.
38
39 A **context** is a "variable name" -> "variable value" mapping that is passed
40 to a template.
41
42 A template **renders** a context by replacing the variable "holes" with values
43 from the context and executing all block tags.
44
45 Using the template system
46 =========================
47
48 Using the template system in Python is a two-step process:
49
50     * First, you compile the raw template code into a ``Template`` object.
51     * Then, you call the ``render()`` method of the ``Template`` object with a
52       given context.
53
54 Compiling a string
55 ------------------
56
57 The easiest way to create a ``Template`` object is by instantiating it
58 directly. The class lives at ``django.core.template.Template``. The constructor
59 takes one argument -- the raw template code::
60
61     >>> from django.core.template import Template
62     >>> t = Template("My name is {{ my_name }}.")
63     >>> print t
64     <django.core.template.Template instance>
65
66 .. admonition:: Behind the scenes
67
68     The system only parses your raw template code once -- when you create the
69     ``Template`` object. From then on, it's stored internally as a "node"
70     structure for performance.
71
72     Even the parsing itself is quite fast. Most of the parsing happens via a
73     single call to a single, short, regular expression.
74
75 Rendering a context
76 -------------------
77
78 Once you have a compiled ``Template`` object, you can render a context -- or
79 multiple contexts -- with it. The ``Context`` class lives at
80 ``django.core.template.Context``, and the constructor takes one (optional)
81 argument: a dictionary mapping variable names to variable values. Call the
82 ``Template`` object's ``render()`` method with the context to "fill" the
83 template::
84
85     >>> from django.core.template import Context, Template
86     >>> t = Template("My name is {{ my_name }}.")
87
88     >>> c = Context({"my_name": "Adrian"})
89     >>> t.render(c)
90     "My name is Adrian."
91
92     >>> c = Context({"my_name": "Dolores"})
93     >>> t.render(c)
94     "My name is Dolores."
95
96 Variable names must consist of any letter (A-Z), any digit (0-9), an underscore
97 or a dot.
98
99 Dots have a special meaning in template rendering. A dot in a variable name
100 signifies **lookup**. Specifically, when the template system encounters a dot
101 in a variable name, it tries the following lookups, in this order:
102
103     * Dictionary lookup. Example: ``foo["bar"]``
104     * Attribute lookup. Example: ``foo.bar``
105     * Method call. Example: ``foo.bar()``
106     * List-index lookup. Example: ``foo[bar]``
107
108 The template system uses the first lookup type that works. It's short-circuit
109 logic.
110
111 Here are a few examples::
112
113     >>> from django.core.template import Context, Template
114     >>> t = Template("My name is {{ person.first_name }}.")
115     >>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
116     >>> t.render(Context(d))
117     "My name is Joe."
118
119     >>> class PersonClass: pass
120     >>> p = PersonClass()
121     >>> p.first_name = "Ron"
122     >>> p.last_name = "Nasty"
123     >>> t.render(Context({"person": p}))
124     "My name is Ron."
125
126     >>> class PersonClass2:
127     ...     def first_name(self):
128     ...         return "Samantha"
129     >>> p = PersonClass2()
130     >>> t.render(Context({"person": p}))
131     "My name is Samantha."
132
133     >>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
134     >>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
135     >>> t.render(c)
136     "The first stooge in the list is Larry."
137
138 If a variable doesn't exist, the template system fails silently. The variable
139 is replaced with an empty string::
140
141     >>> t = Template("My name is {{ my_name }}.")
142     >>> c = Context({"foo": "bar"})
143     >>> t.render(c)
144     "My name is ."
145
146 Method lookups are slightly more complex than the other lookup types. Here are
147 some things to keep in mind:
148
149     * If, during the method lookup, a method raises an exception, the exception
150       will be propagated, unless the exception subclasses
151       ``django.core.template.SilentVariableFailure``. If the exception
152       subclasses ``SilentVariableFailure``, the variable will render as an
153       empty string. Example::
154
155         >>> t = Template("My name is {{ person.first_name }}.")
156         >>> class PersonClass3:
157         ...     def first_name(self):
158         ...         raise AssertionError, "foo"
159         >>> p = PersonClass3()
160         >>> t.render(Context({"person": p}))
161         Traceback (most recent call last):
162         ...
163         AssertionError: foo
164
165         >>> from django.core.template import SilentVariableFailure
166         >>> class SilentAssertionError(SilentVariableFailure): pass
167         >>> class PersonClass4:
168         ...     def first_name(self):
169         ...         raise SilentAssertionError, "foo"
170         >>> p = PersonClass4()
171         >>> t.render(Context({"person": p}))
172         "My name is ."
173
174     * A method call will only work if the method has no required arguments.
175       Otherwise, the system will move to the next lookup type (list-index
176       lookup).
177
178     * Obviously, some methods have side effects, and it'd be either foolish or
179       a security hole to allow the template system to access them.
180
181       A good example is the ``delete()`` method on each Django model object.
182       The template system shouldn't be allowed to do something like this::
183
184         I will now delete this valuable data. {{ data.delete }}
185
186       To prevent this, set a function attribute ``alters_data`` on the method.
187       The template system won't execute a method if the method has
188       ``alters_data=True`` set. The dynamically-generated ``delete()`` and
189       ``save()`` methods on Django model objects get ``alters_data=True``
190       automatically. Example::
191
192         def sensitive_function(self):
193             self.database_record.delete()
194         sensitive_function.alters_data = True
195
196 Playing with Context objects
197 ----------------------------
198
199 Most of the time, you'll instantiate ``Context`` objects by passing in a
200 fully-populated dictionary to ``Context()``. But you can add and delete items
201 from a ``Context`` object once it's been instantiated, too, using standard
202 dictionary syntax::
203
204     >>> c = Context({"foo": "bar"})
205     >>> c['foo']
206     'bar'
207     >>> del c['foo']
208     >>> c['foo']
209     ''
210     >>> c['newvariable'] = 'hello'
211     >>> c['newvariable']
212     'hello'
213
214 A ``Context`` object is a stack. That is, you can ``push()`` and ``pop()`` it.
215 If you ``pop()`` too much, it'll raise
216 ``django.core.template.ContextPopException``::
217
218     >>> c = Context()
219     >>> c['foo'] = 'first level'
220     >>> c.push()
221     >>> c['foo'] = 'second level'
222     >>> c['foo']
223     'second level'
224     >>> c.pop()
225     >>> c['foo']
226     'first level'
227     >>> c['foo'] = 'overwritten'
228     >>> c['foo']
229     'overwritten'
230     >>> c.pop()
231     Traceback (most recent call last):
232     ...
233     django.core.template.ContextPopException
234
235 Using a ``Context`` as a stack comes in handy in some custom template tags, as
236 you'll see below.
237
238 Subclassing Context: DjangoContext
239 ----------------------------------
240
241 Django comes with a special ``Context`` class,
242 ``django.core.extensions.DjangoContext``, that acts slightly differently than
243 the normal ``django.core.template.Context``. It takes an ``HttpRequest`` object
244 as its first argument, and it automatically populates the context with a few
245 variables:
246
247     * ``user`` -- An ``auth.User`` instance representing the currently
248       logged-in user (or an ``AnonymousUser`` instance, if the client isn't
249       logged in). See the `user authentication docs`.
250     * ``messages`` -- A list of ``auth.Message`` objects for the currently
251       logged-in user.
252     * ``perms`` -- An instance of ``django.core.extensions.PermWrapper``,
253       representing the permissions that the currently logged-in user has. See
254       the `permissions docs`_.
255
256 Also, if your ``DEBUG`` setting is set to ``True``, every ``DjangoContext``
257 instance has the following two extra variables:
258
259     * ``debug`` -- ``True``. You can use this in templates to test whether
260       you're in ``DEBUG`` mode.
261     * ``sql_queries`` -- A list of ``{'sql': ..., 'time': ...}`` dictionaries,
262       representing every SQL query that has happened so far during the request
263       and how long it took. The list is in order by query.
264
265 Feel free to subclass ``Context`` yourself if you find yourself wanting to give
266 each template something "automatically." For instance, if you want to give
267 every template automatic access to the current time, use something like this::
268
269     from django.core.template import Context
270     import datetime
271     class TimeContext(Context):
272         def __init__(self, *args, **kwargs):
273             Context.__init__(self, *args, **kwargs)
274             self['current_time'] = datetime.datetime.now()
275
276 This technique has two caveats:
277
278     * You'll have to remember to use ``TimeContext`` instead of ``Context`` in
279       your template-loading code.
280
281     * You'll have to be careful not to set the variable ``current_time`` when
282       you populate this context. If you do, you'll override the other one.
283
284 .. _user authentication docs: http://www.djangoproject.com/documentation/models/authentication/#users
285 .. _permissions docs: http://www.djangoproject.com/documentation/models/authentication/#permissions
286
287 Loading templates
288 -----------------
289
290 Generally, you'll store templates in files on your filesystem rather than using
291 the low-level ``Template`` API yourself. Save templates in a file with an
292 ".html" extension in a directory specified as a **template directory**.
293
294 If you don't like the requirement that templates have an ".html" extension,
295 change your ``TEMPLATE_FILE_EXTENSION`` setting. It's set to ``".html"`` by
296 default.
297
298 Also, the .html extension doesn't mean templates can contain only HTML. They
299 can contain whatever textual content you want.
300
301 The TEMPLATE_DIRS setting
302 ~~~~~~~~~~~~~~~~~~~~~~~~~
303
304 Tell Django what your template directories are by using the ``TEMPLATE_DIRS``
305 setting in your settings file. This should be set to a list or tuple of strings
306 that contain full paths to your template directory(ies). Example::
307
308     TEMPLATE_DIRS = (
309         "/home/html/templates/lawrence.com",
310         "/home/html/templates/default",
311     )
312
313 The Python API
314 ~~~~~~~~~~~~~~
315
316 Django has two ways to load templates from files:
317
318 ``django.core.template.loader.get_template(template_name)``
319     ``get_template`` returns the compiled template (a ``Template`` object) for
320     the template with the given name. If the template doesn't exist, it raises
321     ``django.core.template.TemplateDoesNotExist``.
322
323 ``django.core.template.loader.select_template(template_name_list)``
324     ``select_template`` is just like ``get_template``, except it takes a list
325     of template names. Of the list, it returns the first template that exists.
326
327 For example, if you call ``get_template("story_detail")`` and have the above
328 ``TEMPLATE_DIRS`` setting, here are the files Django will look for, in order:
329
330     * ``/home/html/templates/lawrence.com/story_detail.html``
331     * ``/home/html/templates/default/story_detail.html``
332
333 If you call ``select_template(["story_253_detail", "story_detail"])``, here's
334 what Django will look for:
335
336     * ``/home/html/templates/lawrence.com/story_253_detail.html``
337     * ``/home/html/templates/default/story_253_detail.html``
338     * ``/home/html/templates/lawrence.com/story_detail.html``
339     * ``/home/html/templates/default/story_detail.html``
340
341 When Django finds a template that exists, it stops looking.
342
343 .. admonition:: Tip
344
345     You can use ``select_template`` for super-flexible "templatability." For
346     example, if you've written a news story and want some stories to have
347     custom templates, use something like
348     ``select_template(["story_%s_detail" % story.id, "story_detail"])``.
349     That'll allow you to use a custom template for an individual story, with a
350     fallback template for stories that don't have custom templates.
351
352 Using subdirectories
353 ~~~~~~~~~~~~~~~~~~~~
354
355 It's possible -- and preferable -- to organize templates in subdirectories of
356 the template directory. The convention is to make a subdirectory for each
357 Django app, with subdirectories within those subdirectories as needed.
358
359 Do this for your own sanity. Storing all templates in the root level of a
360 single directory gets messy.
361
362 To load a template that's within a subdirectory, just use a slash, like so::
363
364     get_template("news/story_detail")
365
366 Loader types
367 ~~~~~~~~~~~~
368
369 By default, Django uses a filesystem-based template loader, but Django comes
370 with a few other template loaders. They're disabled by default, but you can
371 activate them by editing your ``TEMPLATE_LOADERS`` setting.
372 ``TEMPLATE_LOADERS`` should be a tuple of strings, where each string represents
373 a template loader. Here are the built-in template loaders:
374
375 ``django.core.template.loaders.filesystem.load_template_source``
376     Loads templates from the filesystem, according to ``TEMPLATE_DIRS``.
377
378 ``django.core.template.loaders.app_directories.load_template_source``
379     Loads templates from Django apps on the filesystem. For each app in
380     ``INSTALLED_APPS``, the loader looks for a ``templates`` subdirectory. If
381     the directory exists, Django looks for templates in there.
382
383     This means you can store templates with your individual apps. This also
384     makes it easy to distribute Django apps with default templates.
385
386     For example, for this setting::
387
388         INSTALLED_APPS = ('myproject.polls', 'myproject.music')
389
390     ...then ``get_template("foo")`` will look for templates in these
391     directories, in this order:
392
393         * ``/path/to/myproject/polls/templates/foo.html``
394         * ``/path/to/myproject/music/templates/music.html``
395
396     Note that the loader performs an optimization when it is first imported:
397     It caches a list of which ``INSTALLED_APPS`` packages have a ``templates``
398     subdirectory.
399
400 ``django.core.template.loaders.eggs.load_template_source``
401     Just like ``app_directories`` above, but it loads templates from Python
402     eggs rather than from the filesystem.
403
404 Django uses the template loaders in order according to the ``TEMPLATE_LOADERS``
405 setting. It uses each loader until a loader finds a match.
406
407 Extending the template system
408 =============================
409
410 Although the Django template language comes with several default tags and
411 filters, you might want to write your own. It's easy to do.
412
413 First, create a ``templatetags`` package in the appropriate Django app's
414 package. It should be on the same level as ``models``, ``views``, etc. For
415 example::
416
417     polls/
418         models/
419         templatetags/
420         views/
421
422 Add two files to the ``templatetags`` package: an ``__init__.py`` file and a
423 file that will contain your custom tag/filter definitions. The name of the
424 latter file is the name you'll use to load the tags later. For example, if your
425 custom tags/filters are in a file called ``poll_extras.py``, you'd do the
426 following in a template::
427
428     {% load poll_extras %}
429
430 The ``{% load %}`` tag looks at your ``INSTALLED_APPS`` setting and only allows
431 the loading of template libraries within installed Django apps. This is a
432 security feature: It allows you to host Python code for many template libraries
433 on a single computer without enabling access to all of them for every Django
434 installation.
435
436 If you write a template library that isn't tied to any particular models/views,
437 it's perfectly OK to have a Django app package that only contains a
438 ``templatetags`` package.
439
440 There's no limit on how many modules you put in the ``templatetags`` package.
441 Just keep in mind that a ``{% load %}`` statement will load tags/filters for
442 the given Python module name, not the name of the app.
443
444 Once you've created that Python module, you'll just have to write a bit of
445 Python code, depending on whether you're writing filters or tags.
446
447 .. admonition:: Behind the scenes
448
449     For a ton of examples, read the source code for Django's default filters
450     and tags. They're in ``django/core/template/defaultfilters.py`` and
451     ``django/core/template/defaulttags.py``, respectively.
452
453 Writing custom template filters
454 -------------------------------
455
456 Custom filters are just Python functions that take two arguments:
457
458     * The value of the variable (input) -- not necessarily a string
459     * The value of the argument -- always a string
460
461 Filter functions should always return something. They shouldn't raise
462 exceptions. They should fail silently. In case of error, they should return
463 either the original input or an empty string -- whichever makes more sense.
464
465 Here's an example filter definition::
466
467     def cut(value, arg):
468         "Removes all values of arg from the given string"
469         return value.replace(arg, '')
470
471 Most filters don't take arguments. For filters that don't take arguments, the
472 convention is to use a single underscore as the second argument to the filter
473 definition. Example::
474
475     def lower(value, _):
476         "Converts a string into all lowercase"
477         return value.lower()
478
479 When you've written your filter definition, you need to register it, to make it
480 available to Django's template language::
481
482     from django.core import template
483     template.register_filter('cut', cut, True)
484     template.register_filter('lower', lower, False)
485
486 ``register_filter`` takes three arguments:
487
488     1. The name of the filter -- a string.
489     2. The compilation function -- a Python function (not the name of the
490        function as a string).
491     3. A boolean, designating whether the filter requires an argument. This
492        tells Django's template parser whether to throw ``TemplateSyntaxError``
493        when filter arguments are given (or missing).
494
495 The convention is to put all ``register_filter`` calls at the bottom of your
496 template-library module.
497
498 Writing custom template tags
499 ----------------------------
500
501 Tags are more complex than filters, because tags can do anything.
502
503 A quick overview
504 ~~~~~~~~~~~~~~~~
505
506 Above, this document explained that the template system works in a two-step
507 process: compiling and rendering. To define a custom template tag, you specify
508 how the compilation works and how the rendering works.
509
510 When Django compiles a template, it splits the raw template text into
511 ''nodes''. Each node is an instance of ``django.core.template.Node`` and has
512 a ``render()`` method. A compiled template is, simply, a list of ``Node``
513 objects. When you call ``render()`` on a compiled template object, the template
514 calls ``render()`` on each ``Node`` in its node list, with the given context.
515 The results are all concatenated together to form the output of the template.
516
517 Thus, to define a custom template tag, you specify how the raw template tag is
518 converted into a ``Node`` (the compilation function), and what the node's
519 ``render()`` method does.
520
521 Writing the compilation function
522 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
523
524 For each template tag the template parser encounters, it calls a Python
525 function with the tag contents and the parser object itself. This function is
526 responsible for returning a ``Node`` instance based on the contents of the tag.
527
528 By convention, the name of each compilation function should start with ``do_``.
529
530 For example, let's write a template tag, ``{% current_time %}``, that displays
531 the current date/time, formatted according to a parameter given in the tag, in
532 `strftime syntax`_. It's a good idea to decide the tag syntax before anything
533 else. In our case, let's say the tag should be used like this::
534
535     <p>The time is {% current_time "%Y-%M-%d %I:%M %p" %}.</p>
536
537 .. _`strftime syntax`: http://www.python.org/doc/current/lib/module-time.html#l2h-1941
538
539 The parser for this function should grab the parameter and create a ``Node``
540 object::
541
542     from django.core import template
543     def do_current_time(parser, token):
544         try:
545             # Splitting by None == splitting by spaces.
546             tag_name, format_string = token.contents.split(None, 1)
547         except ValueError:
548             raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0]
549         if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
550             raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
551         return CurrentTimeNode(format_string[1:-1])
552
553 Notes:
554
555     * ``parser`` is the template parser object. We don't need it in this
556       example.
557
558     * ``token.contents`` is a string of the raw contents of the tag. In our
559       example, it's ``'current_time "%Y-%M-%d %I:%M %p"'``.
560
561     * This function is responsible for raising
562       ``django.core.template.TemplateSyntaxError``, with helpful messages, for
563       any syntax error.
564
565     * The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable.
566       Don't hard-code the tag's name in your error messages, because that
567       couples the tag's name to your function. ``token.contents.split()[0]``
568       will ''always'' be the name of your tag -- even when the tag has no
569       arguments.
570
571     * The function returns a ``CurrentTimeNode`` with everything the node needs
572       to know about this tag. In this case, it just passes the argument --
573       ``"%Y-%M-%d %I:%M %p"``. The leading and trailing quotes from the
574       template tag are removed in ``format_string[1:-1]``.
575
576     * The parsing is very low-level. The Django developers have experimented
577       with writing small frameworks on top of this parsing system, using
578       techniques such as EBNF grammars, but those experiments made the template
579       engine too slow. It's low-level because that's fastest.
580
581 Writing the renderer
582 ~~~~~~~~~~~~~~~~~~~~
583
584 The second step in writing custom tags is to define a ``Node`` subclass that
585 has a ``render()`` method.
586
587 Continuing the above example, we need to define ``CurrentTimeNode``::
588
589     from django.core import template
590     import datetime
591     class CurrentTimeNode(template.Node):
592         def __init__(self, format_string):
593             self.format_string = format_string
594         def render(self, context):
595             return datetime.datetime.now().strftime(self.format_string)
596
597 Notes:
598
599     * ``__init__()`` gets the ``format_string`` from ``do_current_time()``.
600       Always pass any options/parameters/arguments to a ``Node`` via its
601       ``__init__()``.
602
603     * The ``render()`` method is where the work actually happens.
604
605     * ``render()`` should never raise ``TemplateSyntaxError`` or any other
606       exception. It should fail silently, just as template filters should.
607
608 Ultimately, this decoupling of compilation and rendering results in an
609 efficient template system, because a template can render multiple context
610 without having to be parsed multiple times.
611
612 Registering the tag
613 ~~~~~~~~~~~~~~~~~~~
614
615 Finally, use a ``register_tag`` call, as in ``register_filter`` above. Example::
616
617     from django.core import template
618     template.register_tag('current_time', do_current_time)
619
620 ``register_tag`` takes two arguments:
621
622     1. The name of the template tag -- a string.
623     2. The compilation function -- a Python function (not the name of the
624        function as a string).
625
626 Setting a variable in the context
627 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
628
629 The above example simply output a value. Generally, it's more flexible if your
630 template tags set template variables instead of outputting values. That way,
631 template authors can reuse the values that your template tags create.
632
633 To set a variable in the context, just use dictionary assignment on the context
634 object in the ``render()`` method. Here's an updated version of
635 ``CurrentTimeNode`` that sets a template variable ``current_time`` instead of
636 outputting it::
637
638     class CurrentTimeNode2(template.Node):
639         def __init__(self, format_string):
640             self.format_string = format_string
641         def render(self, context):
642             context['current_time'] = datetime.datetime.now().strftime(self.format_string)
643             return ''
644
645 Note that ``render()`` returns the empty string. ``render()`` should always
646 return string output. If all the template tag does is set a variable,
647 ``render()`` should return the empty string.
648
649 Here's how you'd use this new version of the tag::
650
651     {% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p>
652
653 But, there's a problem with ``CurrentTimeNode2``: The variable name
654 ``current_time`` is hard-coded. This means you'll need to make sure your
655 template doesn't use ``{{ current_time }}`` anywhere else, because the
656 ``{% current_time %}`` will blindly overwrite that variable's value. A cleaner
657 solution is to make the template tag specify the name of the output variable,
658 like so::
659
660     {% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
661     <p>The current time is {{ my_current_time }}.</p>
662
663 To do that, you'll need to refactor both the compilation function and ``Node``
664 class, like so::
665
666     class CurrentTimeNode3(template.Node):
667         def __init__(self, format_string, var_name):
668             self.format_string = format_string
669             self.var_name = var_name
670         def render(self, context):
671             context[self.var_name] = datetime.datetime.now().strftime(self.format_string)
672             return ''
673
674     import re
675     def do_current_time(parser, token):
676         # This version uses a regular expression to parse tag contents.
677         try:
678             # Splitting by None == splitting by spaces.
679             tag_name, arg = token.contents.split(None, 1)
680         except ValueError:
681             raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents[0]
682         m = re.search(r'(.*?) as (\w+)', arg)
683         if not m:
684             raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
685         format_string, var_name = m.groups()
686         if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
687             raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
688         return CurrentTimeNode3(format_string[1:-1], var_name)
689
690 The difference here is that ``do_current_time()`` grabs the format string and
691 the variable name, passing both to ``CurrentTimeNode3``.
692
693 Parsing until another block tag
694 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
695
696 Template tags can work in tandem. For instance, the standard ``{% comment %}``
697 tag hides everything until ``{% endcomment %}``. To create a template tag such
698 as this, use ``parser.parse()`` in your compilation function.
699
700 Here's how the standard ``{% comment %}`` tag is implemented::
701
702     def do_comment(parser, token):
703         nodelist = parser.parse(('endcomment',))
704         parser.delete_first_token()
705         return CommentNode()
706
707     class CommentNode(template.Node):
708         def render(self, context):
709             return ''
710
711 ``parser.parse()`` takes a tuple of names of block tags ''to parse until''. It
712 returns an instance of ``django.core.template.NodeList``, which is a list of
713 all ``Node`` objects that the parser encountered ''before'' it encountered
714 any of the tags named in the tuple.
715
716 In ``"nodelist = parser.parse(('endcomment',))"`` in the above example,
717 ``nodelist`` is a list of all nodes between the ``{% comment %}`` and
718 ``{% endcomment %}``, not counting ``{% comment %}`` and ``{% endcomment %}``
719 themselves.
720
721 After ``parser.parse()`` is called, the parser hasn't yet "consumed" the
722 ``{% endcomment %}`` tag, so the code needs to explicitly call
723 ``parser.delete_first_token()``.
724
725 ``CommentNode.render()`` simply returns an empty string. Anything between
726 ``{% comment %}`` and ``{% endcomment %}`` is ignored.
727
728 Parsing until another block tag, and saving contents
729 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
730
731 In the previous example, ``do_comment()`` discarded everything between
732 ``{% comment %}`` and ``{% endcomment %}``. Instead of doing that, it's
733 possible to do something with the code between block tags.
734
735 For example, here's a custom template tag, ``{% upper %}``, that capitalizes
736 everything between itself and ``{% endupper %}``.
737
738 Usage::
739
740     {% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %}
741
742 As in the previous example, we'll use ``parser.parse()``. But this time, we
743 pass the resulting ``nodelist`` to the ``Node``::
744
745     def do_upper(parser, token):
746         nodelist = parser.parse(('endupper',))
747         parser.delete_first_token()
748         return UpperNode(nodelist)
749
750     class UpperNode(template.Node):
751         def __init__(self, nodelist):
752             self.nodelist = nodelist
753         def render(self, context):
754             output = self.nodelist.render(context)
755             return output.upper()
756
757 The only new concept here is the ``self.nodelist.render(context)`` in
758 ``UpperNode.render()``.
759
760 For more examples of complex rendering, see the source code for ``{% if %}``,
761 ``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
762 ``django/core/template/defaulttags.py``.
Note: See TracBrowser for help on using the browser.