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
|
||||
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
|
||||
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,
|
||||
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.
|
||||
|
||||
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