Added docs/templates_python.txt, which isn't finished yet
git-svn-id: http://code.djangoproject.com/svn/django/trunk@623 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
e5a801590a
commit
096ad32c84
|
@ -1,6 +1,6 @@
|
||||||
============================
|
==================================================
|
||||||
The Django template language
|
The Django template language: For template authors
|
||||||
============================
|
==================================================
|
||||||
|
|
||||||
Django's template language is designed to strike a balance between power and
|
Django's template language is designed to strike a balance between power and
|
||||||
ease. It's designed to feel comfortable to those used to working with HTML. If
|
ease. It's designed to feel comfortable to those used to working with HTML. If
|
||||||
|
@ -45,7 +45,7 @@ explained later in this document.::
|
||||||
Why use a text-based template instead of an XML-based one (like Zope's
|
Why use a text-based template instead of an XML-based one (like Zope's
|
||||||
TAL)? We wanted Django's template language to be usable for more than
|
TAL)? We wanted Django's template language to be usable for more than
|
||||||
just XML/HTML templates. At World Online, we use it for e-mails,
|
just XML/HTML templates. At World Online, we use it for e-mails,
|
||||||
Javascript and CSV. You can use the template language for any text-based
|
JavaScript and CSV. You can use the template language for any text-based
|
||||||
format.
|
format.
|
||||||
|
|
||||||
What's a variable?
|
What's a variable?
|
||||||
|
|
|
@ -0,0 +1,275 @@
|
||||||
|
====================================================
|
||||||
|
The Django template language: For Python programmers
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
This document explains the Django template system from a technical
|
||||||
|
perspective -- how it works and how to extend it. If you're just looking for
|
||||||
|
reference on the language syntax, see
|
||||||
|
`The Django template language: For template authors`_.
|
||||||
|
|
||||||
|
.. _`The Django template language: For template authors`: http://www.djangoproject.com/documentation/templates/
|
||||||
|
|
||||||
|
Basics
|
||||||
|
======
|
||||||
|
|
||||||
|
A **template** is a text document, or a normal Python string, that is marked-up
|
||||||
|
using the Django template language. A template can contain **block tags** or
|
||||||
|
**variables**.
|
||||||
|
|
||||||
|
A **block tag** is a symbol within a template that does something.
|
||||||
|
|
||||||
|
This definition is deliberately vague. For example, a block tag can output
|
||||||
|
content, serve as a control structure (an "if" statement or "for" loop), grab
|
||||||
|
content from a database or enable access to other template tags.
|
||||||
|
|
||||||
|
Block tags are surrounded by ``"{%"`` and ``"%}"``.
|
||||||
|
|
||||||
|
Example template with block tags::
|
||||||
|
|
||||||
|
{% if is_logged_in %}Thanks for logging in!{% else %}Please log in.{% endif %}
|
||||||
|
|
||||||
|
A **variable** is a symbol within a template that outputs a value.
|
||||||
|
|
||||||
|
Block tags are surrounded by ``"{{"`` and ``"}}"``.
|
||||||
|
|
||||||
|
Example template with variables::
|
||||||
|
|
||||||
|
My first name is {{ first_name }}. My last name is {{ last_name }}.
|
||||||
|
|
||||||
|
A **context** is a "variable name" -> "variable value" mapping that is passed
|
||||||
|
to a template.
|
||||||
|
|
||||||
|
A template **renders** a context by replacing the variable "holes" with values
|
||||||
|
from the context and executing all block tags.
|
||||||
|
|
||||||
|
Using the template system
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Using the template system in Python is a two-step process:
|
||||||
|
|
||||||
|
* First, you compile the raw template code into a ``Template`` object.
|
||||||
|
* Then, you call the ``render()`` method of the ``Template`` object with a
|
||||||
|
given context.
|
||||||
|
|
||||||
|
Compiling a string
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The easiest way to create a ``Template`` object is by instantiating it
|
||||||
|
directly. The class lives at ``django.core.template.Template``. The constructor
|
||||||
|
takes one argument -- the raw template code::
|
||||||
|
|
||||||
|
>>> from django.core.template import Template
|
||||||
|
>>> t = Template("My name is {{ my_name }}.")
|
||||||
|
>>> print t
|
||||||
|
<django.core.template.Template instance>
|
||||||
|
|
||||||
|
.. admonition:: Behind the scenes
|
||||||
|
|
||||||
|
The system only parses your raw template code once -- when you create the
|
||||||
|
``Template`` object. From then on, it's stored internally as a "node"
|
||||||
|
structure for performance.
|
||||||
|
|
||||||
|
Even the parsing itself is quite fast. Most of the parsing happens via a
|
||||||
|
single call to a single, short, regular expression.
|
||||||
|
|
||||||
|
Rending a context
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Once you have a compiled ``Template`` object, you can render a context -- or
|
||||||
|
multiple contexts -- with it. The ``Context`` class lives at
|
||||||
|
``django.core.template.Context``, and the constructor takes one (optional)
|
||||||
|
argument: a dictionary mapping variable names to variable values. Call the
|
||||||
|
``Template`` object's ``render()`` method with the context to "fill" the
|
||||||
|
template::
|
||||||
|
|
||||||
|
>>> from django.core.template import Context, Template
|
||||||
|
>>> t = Template("My name is {{ my_name }}.")
|
||||||
|
|
||||||
|
>>> c = Context({"my_name": "Adrian"})
|
||||||
|
>>> t.render(c)
|
||||||
|
"My name is Adrian."
|
||||||
|
|
||||||
|
>>> c = Context({"my_name": "Dolores"})
|
||||||
|
>>> t.render(c)
|
||||||
|
"My name is Dolores."
|
||||||
|
|
||||||
|
Variable names must consist of any letter (A-Z), any digit (0-9), an underscore
|
||||||
|
or a dot.
|
||||||
|
|
||||||
|
Dots have a special meaning in template rendering. A dot in a variable name
|
||||||
|
signifies **lookup**. Specifically, when the template system encounters a dot
|
||||||
|
in a variable name, it tries the following lookups, in this order:
|
||||||
|
|
||||||
|
* Dictionary lookup. Example: ``foo["bar"]``
|
||||||
|
* Attribute lookup. Example: ``foo.bar``
|
||||||
|
* Method call. Example: ``foo.bar()``
|
||||||
|
* List-index lookup. Example: ``foo[bar]``
|
||||||
|
|
||||||
|
The template system uses the first lookup type that works. It's short-circuit
|
||||||
|
logic.
|
||||||
|
|
||||||
|
Here are a few examples::
|
||||||
|
|
||||||
|
>>> from django.core.template import Context, Template
|
||||||
|
>>> t = Template("My name is {{ person.first_name }}.")
|
||||||
|
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
|
||||||
|
>>> t.render(Context(d))
|
||||||
|
"My name is Joe."
|
||||||
|
|
||||||
|
>>> class PersonClass: pass
|
||||||
|
>>> p = PersonClass()
|
||||||
|
>>> p.first_name = "Ron"
|
||||||
|
>>> p.last_name = "Nasty"
|
||||||
|
>>> t.render(Context({"person": p}))
|
||||||
|
"My name is Ron."
|
||||||
|
|
||||||
|
>>> class PersonClass2:
|
||||||
|
... def first_name(self):
|
||||||
|
... return "Samantha"
|
||||||
|
>>> p = PersonClass2()
|
||||||
|
>>> t.render(Context({"person": p}))
|
||||||
|
"My name is Samantha."
|
||||||
|
|
||||||
|
>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
|
||||||
|
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
|
||||||
|
>>> t.render(c)
|
||||||
|
"The first stooge in the list is Larry."
|
||||||
|
|
||||||
|
If a variable doesn't exist, the template system fails silently. The variable
|
||||||
|
is replaced with an empty string.
|
||||||
|
|
||||||
|
>>> t = Template("My name is {{ my_name }}.")
|
||||||
|
>>> c = Context({"foo": "bar"})
|
||||||
|
>>> t.render(c)
|
||||||
|
"My name is ."
|
||||||
|
|
||||||
|
Method lookups are slightly more complex than the other lookup types. Here are
|
||||||
|
some things to keep in mind:
|
||||||
|
|
||||||
|
* If, during the method lookup, a method raises an exception, the exception
|
||||||
|
will be propgated, unless the exception subclasses
|
||||||
|
``django.core.template.SilentVariableFailure``. If the exception
|
||||||
|
subclasses ``SilentVariableFailure``, the variable will render as an
|
||||||
|
empty string. Example::
|
||||||
|
|
||||||
|
>>> t = Template("My name is {{ person.first_name }}.")
|
||||||
|
>>> class PersonClass3:
|
||||||
|
... def first_name(self):
|
||||||
|
... raise AssertionError, "foo"
|
||||||
|
>>> p = PersonClass3()
|
||||||
|
>>> t.render(Context({"person": p}))
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
AssertionError: foo
|
||||||
|
|
||||||
|
>>> from django.core.template import SilentVariableFailure
|
||||||
|
>>> class SilentAssertionError(SilentVariableFailure): pass
|
||||||
|
>>> class PersonClass4:
|
||||||
|
... def first_name(self):
|
||||||
|
... raise SilentAssertionError, "foo"
|
||||||
|
>>> p = PersonClass4()
|
||||||
|
>>> t.render(Context({"person": p}))
|
||||||
|
"My name is ."
|
||||||
|
|
||||||
|
* A method call will only work if the method has no required arguments.
|
||||||
|
Otherwise, the system will move to the next lookup type (list-index
|
||||||
|
lookup).
|
||||||
|
|
||||||
|
* Obviously, some methods have side effects, and it'd be either foolish or
|
||||||
|
a security hole to allow the template system to access them.
|
||||||
|
|
||||||
|
A good example is the ``delete()`` method on each Django model object.
|
||||||
|
The template system shouldn't be allowed to do something like this::
|
||||||
|
|
||||||
|
I will now delete this valuable data. {{ data.delete }}
|
||||||
|
|
||||||
|
To prevent this, set a function attribute ``alters_data`` on the method.
|
||||||
|
The template system won't execute a method if the method has
|
||||||
|
``alters_data=True`` set. The dynamically-generated ``delete()`` and
|
||||||
|
``save()`` methods on Django model objects get ``alters_data=True``
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
Loading templates
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Generally, you'll store templates in files on your filesystem rather than using
|
||||||
|
the low-level ``Template`` API yourself. Save templates in a file with an
|
||||||
|
".html" extension in a directory specified as a **template directory**.
|
||||||
|
|
||||||
|
(The ".html" extension is just a required convention. It doesn't mean templates
|
||||||
|
can only contain HTML. They can contain whatever textual content you want.)
|
||||||
|
|
||||||
|
The TEMPLATE_DIRS setting
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Tell Django what your template directories are by using the ``TEMPLATE_DIRS``
|
||||||
|
setting in your settings file. This should be set to a list or tuple of strings
|
||||||
|
that contain full paths to your template directory(ies). Example::
|
||||||
|
|
||||||
|
TEMPLATE_DIRS = (
|
||||||
|
"/home/html/templates/lawrence.com",
|
||||||
|
"/home/html/templates/default",
|
||||||
|
)
|
||||||
|
|
||||||
|
The Python API
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Django has two ways to load templates from files:
|
||||||
|
|
||||||
|
``django.core.template_loader.get_template(template_name)``
|
||||||
|
``get_template`` returns the compiled template (a ``Template`` object) for
|
||||||
|
the given name. If the template doesn't exist, it raises
|
||||||
|
``django.core.template.TemplateDoesNotExist``.
|
||||||
|
|
||||||
|
``django.core.template_loader.select_template(template_name_list)``
|
||||||
|
``select_template`` is just like ``get_template``, except it takes a list
|
||||||
|
of template names. Of the list, it returns the first template that exists.
|
||||||
|
|
||||||
|
For example, if you call ``get_template("story_detail")`` and have the above
|
||||||
|
``TEMPLATE_DIRS`` setting, here are the files Django will look for, in order:
|
||||||
|
|
||||||
|
* ``/home/html/templates/lawrence.com/story_detail.html``
|
||||||
|
* ``/home/html/templates/default/story_detail.html``
|
||||||
|
|
||||||
|
If you call ``select_template(["story_253_detail", "story_detail"])``, here's
|
||||||
|
what Django will look for:
|
||||||
|
|
||||||
|
* ``/home/html/templates/lawrence.com/story_253_detail.html``
|
||||||
|
* ``/home/html/templates/default/story_253_detail.html``
|
||||||
|
* ``/home/html/templates/lawrence.com/story_detail.html``
|
||||||
|
* ``/home/html/templates/default/story_detail.html``
|
||||||
|
|
||||||
|
When Django finds a template that exists, it stops looking.
|
||||||
|
|
||||||
|
.. admonition:: Tip
|
||||||
|
|
||||||
|
You can use ``select_template`` for super-flexible "templatability." For
|
||||||
|
example, if you've written a news story and want some stories to have
|
||||||
|
custom templates, use something like
|
||||||
|
``select_template(["story_%s_detail" % story.id, "story_detail"])``.
|
||||||
|
That'll allow you to use a custom template for an individual story, with a
|
||||||
|
fallback template for stories that don't have custom templates.
|
||||||
|
|
||||||
|
Using subdirectories
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
It's possible -- and preferable -- to organize templates in subdirectories of
|
||||||
|
the template directory. The convention is to make a subdirectory for each
|
||||||
|
Django app, with subdirectories within those subdirectories as needed.
|
||||||
|
|
||||||
|
Do this for your own sanity. Storing all templates in the root level of a
|
||||||
|
single directory gets messy.
|
||||||
|
|
||||||
|
To load a template that's within a subdirectory, just use a slash, like so::
|
||||||
|
|
||||||
|
get_template("news/story_detail")
|
||||||
|
|
||||||
|
Extending the template system
|
||||||
|
=============================
|
||||||
|
|
||||||
|
Writing custom template filters
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Writing custom template tags
|
||||||
|
----------------------------
|
||||||
|
|
Loading…
Reference in New Issue