diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2006-05-02 01:31:56 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2006-05-02 01:31:56 +0000 |
| commit | f69cf70ed813a8cd7e1f963a14ae39103e8d5265 (patch) | |
| tree | d3b32e84cd66573b3833ddf662af020f8ef2f7a8 /docs/templates_python.txt | |
| parent | d5dbeaa9be359a4c794885c2e9f1b5a7e5e51fb8 (diff) | |
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2809 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/templates_python.txt')
| -rw-r--r-- | docs/templates_python.txt | 144 |
1 files changed, 76 insertions, 68 deletions
diff --git a/docs/templates_python.txt b/docs/templates_python.txt index b1d968cd47..21ae595624 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -55,13 +55,13 @@ 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 +directly. The class lives at ``django.template.Template``. The constructor takes one argument -- the raw template code:: - >>> from django.core.template import Template + >>> from django.template import Template >>> t = Template("My name is {{ my_name }}.") >>> print t - <django.core.template.Template instance> + <django.template.Template instance> .. admonition:: Behind the scenes @@ -77,12 +77,12 @@ Rendering 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) +``django.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 + >>> from django.template import Context, Template >>> t = Template("My name is {{ my_name }}.") >>> c = Context({"my_name": "Adrian"}) @@ -110,7 +110,7 @@ logic. Here are a few examples:: - >>> from django.core.template import Context, Template + >>> from django.template import Context, Template >>> t = Template("My name is {{ person.first_name }}.") >>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}} >>> t.render(Context(d)) @@ -139,10 +139,10 @@ 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 propagated, unless the exception subclasses - ``django.core.template.SilentVariableFailure``. If the exception - subclasses ``SilentVariableFailure``, the variable will render as an - empty string. Example:: + will be propagated, unless the exception has an attribute + ``silent_variable_failure`` whose value is ``True``. If the exception + *does* have a ``silent_variable_failure`` attribute, the variable will + render as an empty string. Example:: >>> t = Template("My name is {{ person.first_name }}.") >>> class PersonClass3: @@ -154,15 +154,21 @@ some things to keep in mind: ... AssertionError: foo - >>> from django.core.template import SilentVariableFailure - >>> class SilentAssertionError(SilentVariableFailure): pass + >>> class SilentAssertionError(Exception): + ... silent_variable_failure = True >>> class PersonClass4: ... def first_name(self): - ... raise SilentAssertionError, "foo" + ... raise SilentAssertionError >>> p = PersonClass4() >>> t.render(Context({"person": p})) "My name is ." + Note that ``django.core.exceptions.ObjectDoesNotExist``, which is the + base class for all Django database API ``DoesNotExist`` exceptions, has + ``silent_variable_failure = True``. So if you're using Django templates + with Django model objects, any ``DoesNotExist`` exception will fail + silently. + * 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). @@ -203,9 +209,9 @@ This applies to any level of lookup:: >>> t.render(c) "My name is Stan ." -In the Django development version, if a variable doesn't exist, the template -system inserts the value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which -is set to ``''`` (the empty string) by default. +If a variable doesn't exist, the template system inserts the value of the +``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty +string) by default. Playing with Context objects ---------------------------- @@ -227,7 +233,7 @@ dictionary syntax:: A ``Context`` object is a stack. That is, you can ``push()`` and ``pop()`` it. If you ``pop()`` too much, it'll raise -``django.core.template.ContextPopException``:: +``django.template.ContextPopException``:: >>> c = Context() >>> c['foo'] = 'first level' @@ -244,20 +250,20 @@ If you ``pop()`` too much, it'll raise >>> c.pop() Traceback (most recent call last): ... - django.core.template.ContextPopException + django.template.ContextPopException Using a ``Context`` as a stack comes in handy in some custom template tags, as you'll see below. -Subclassing Context: DjangoContext ----------------------------------- +Subclassing Context: RequestContext +----------------------------------- Django comes with a special ``Context`` class, -``django.core.extensions.DjangoContext``, that acts slightly differently than -the normal ``django.core.template.Context``. The first difference is that takes +``django.template.RequestContext``, that acts slightly differently than +the normal ``django.template.Context``. The first difference is that takes an `HttpRequest object`_ as its first argument. For example:: - c = DjangoContext(request, { + c = RequestContext(request, { 'foo': 'bar', } @@ -277,16 +283,16 @@ variable to the context and a second processor adds a variable with the same name, the second will override the first. The default processors are explained below. -Also, you can give ``DjangoContext`` a list of additional processors, using the +Also, you can give ``RequestContext`` a list of additional processors, using the optional, third positional argument, ``processors``. In this example, the -``DjangoContext`` instance gets a ``ip_address`` variable:: +``RequestContext`` instance gets a ``ip_address`` variable:: def ip_address_processor(request): return {'ip_address': request.META['REMOTE_ADDR']} def some_view(request): # ... - return DjangoContext(request, { + return RequestContext(request, { 'foo': 'bar', }, [ip_address_processor]) @@ -299,7 +305,7 @@ django.core.context_processors.auth ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every -``DjangoContext`` will contain these three variables: +``RequestContext`` will contain these three variables: * ``user`` -- An ``auth.User`` instance representing the currently logged-in user (or an ``AnonymousUser`` instance, if the client isn't @@ -317,7 +323,7 @@ django.core.context_processors.debug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every -``DjangoContext`` will contain these two variables -- but only if your +``RequestContext`` will contain these two variables -- but only if your ``DEBUG`` setting is set to ``True`` and the request's IP address (``request.META['REMOTE_ADDR']``) is in the ``INTERNAL_IPS`` setting: @@ -331,7 +337,7 @@ django.core.context_processors.i18n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every -``DjangoContext`` will contain these two variables: +``RequestContext`` will contain these two variables: * ``LANGUAGES`` -- The value of the `LANGUAGES setting`_. * ``LANGUAGE_CODE`` -- ``request.LANGUAGE_CODE``, if it exists. Otherwise, @@ -346,8 +352,6 @@ See the `internationalization docs`_ for more. django.core.context_processors.request ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**New in Django development version** - If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every ``DjangoContext`` will contain a variable ``request``, which is the current `HttpRequest object`_. Note that this processor is not enabled by default; @@ -357,15 +361,8 @@ 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**. - -If you don't like the requirement that templates have an ".html" extension, -change your ``TEMPLATE_FILE_EXTENSION`` setting. It's set to ``".html"`` by -default. - -Also, the .html extension doesn't mean templates can contain only HTML. They -can contain whatever textual content you want. +the low-level ``Template`` API yourself. Save templates in a directory +specified as a **template directory**. The TEMPLATE_DIRS setting ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -380,7 +377,8 @@ that contain full paths to your template directory(ies). Example:: ) Your templates can go anywhere you want, as long as the directories and -templates are readable by the Web server. +templates are readable by the Web server. They can have any extension you want, +such as ``.html`` or ``.txt``, or they can have no extension at all. Note that these paths should use Unix-style forward slashes, even on Windows. @@ -389,23 +387,24 @@ The Python API Django has two ways to load templates from files: -``django.core.template.loader.get_template(template_name)`` +``django.template.loader.get_template(template_name)`` ``get_template`` returns the compiled template (a ``Template`` object) for the template with the given name. If the template doesn't exist, it raises - ``django.core.template.TemplateDoesNotExist``. + ``django.template.TemplateDoesNotExist``. -``django.core.template.loader.select_template(template_name_list)`` +``django.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: +For example, if you call ``get_template('story_detail.html')`` 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: +If you call ``select_template(['story_253_detail.html', 'story_detail.html'])``, +here's what Django will look for: * ``/home/html/templates/lawrence.com/story_253_detail.html`` * ``/home/html/templates/default/story_253_detail.html`` @@ -416,10 +415,10 @@ When Django finds a template that exists, it stops looking. .. admonition:: Tip - You can use ``select_template`` for super-flexible "templatability." For + 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"])``. + ``select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])``. 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. @@ -435,21 +434,30 @@ single directory gets messy. To load a template that's within a subdirectory, just use a slash, like so:: - get_template("news/story_detail") + get_template('news/story_detail.html') + +Using the same ``TEMPLATE_DIRS`` setting from above, this example +``get_template()`` call will attempt to load the following templates: + + * ``/home/html/templates/lawrence.com/news/story_detail.html`` + * ``/home/html/templates/default/news/story_detail.html`` Loader types ~~~~~~~~~~~~ By default, Django uses a filesystem-based template loader, but Django comes -with a few other template loaders. They're disabled by default, but you can -activate them by editing your ``TEMPLATE_LOADERS`` setting. -``TEMPLATE_LOADERS`` should be a tuple of strings, where each string represents -a template loader. Here are the built-in template loaders: +with a few other template loaders, which know how to load templates from other +sources. + +These other loaders are disabled by default, but you can activate them by +editing your ``TEMPLATE_LOADERS`` setting. ``TEMPLATE_LOADERS`` should be a +tuple of strings, where each string represents a template loader. Here are the +template loaders that come with Django: -``django.core.template.loaders.filesystem.load_template_source`` +``django.template.loaders.filesystem.load_template_source`` Loads templates from the filesystem, according to ``TEMPLATE_DIRS``. -``django.core.template.loaders.app_directories.load_template_source`` +``django.template.loaders.app_directories.load_template_source`` Loads templates from Django apps on the filesystem. For each app in ``INSTALLED_APPS``, the loader looks for a ``templates`` subdirectory. If the directory exists, Django looks for templates in there. @@ -461,7 +469,7 @@ a template loader. Here are the built-in template loaders: INSTALLED_APPS = ('myproject.polls', 'myproject.music') - ...then ``get_template("foo")`` will look for templates in these + ...then ``get_template('foo.html')`` will look for templates in these directories, in this order: * ``/path/to/myproject/polls/templates/foo.html`` @@ -471,7 +479,7 @@ a template loader. Here are the built-in template loaders: It caches a list of which ``INSTALLED_APPS`` packages have a ``templates`` subdirectory. -``django.core.template.loaders.eggs.load_template_source`` +``django.template.loaders.eggs.load_template_source`` Just like ``app_directories`` above, but it loads templates from Python eggs rather than from the filesystem. @@ -521,15 +529,15 @@ To be a valid tag library, the module contain a module-level variable named ``register`` that is a ``template.Library`` instance, in which all the tags and filters are registered. So, near the top of your module, put the following:: - from django.core import template + from django import template register = template.Library() .. admonition:: Behind the scenes For a ton of examples, read the source code for Django's default filters - and tags. They're in ``django/core/template/defaultfilters.py`` and - ``django/core/template/defaulttags.py``, respectively. + and tags. They're in ``django/template/defaultfilters.py`` and + ``django/template/defaulttags.py``, respectively. Writing custom template filters ------------------------------- @@ -603,7 +611,7 @@ process: compiling and rendering. To define a custom template tag, you specify how the compilation works and how the rendering works. When Django compiles a template, it splits the raw template text into -''nodes''. Each node is an instance of ``django.core.template.Node`` and has +''nodes''. Each node is an instance of ``django.template.Node`` and has a ``render()`` method. A compiled template is, simply, a list of ``Node`` objects. When you call ``render()`` on a compiled template object, the template calls ``render()`` on each ``Node`` in its node list, with the given context. @@ -632,7 +640,7 @@ else. In our case, let's say the tag should be used like this:: The parser for this function should grab the parameter and create a ``Node`` object:: - from django.core import template + from django import template def do_current_time(parser, token): try: # Splitting by None == splitting by spaces. @@ -652,7 +660,7 @@ Notes: example, it's ``'current_time "%Y-%M-%d %I:%M %p"'``. * This function is responsible for raising - ``django.core.template.TemplateSyntaxError``, with helpful messages, for + ``django.template.TemplateSyntaxError``, with helpful messages, for any syntax error. * The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable. @@ -679,7 +687,7 @@ has a ``render()`` method. Continuing the above example, we need to define ``CurrentTimeNode``:: - from django.core import template + from django import template import datetime class CurrentTimeNode(template.Node): def __init__(self, format_string): @@ -817,7 +825,7 @@ Here's how the standard ``{% comment %}`` tag is implemented:: return '' ``parser.parse()`` takes a tuple of names of block tags ''to parse until''. It -returns an instance of ``django.core.template.NodeList``, which is a list of +returns an instance of ``django.template.NodeList``, which is a list of all ``Node`` objects that the parser encountered ''before'' it encountered any of the tags named in the tuple. @@ -867,4 +875,4 @@ The only new concept here is the ``self.nodelist.render(context)`` in For more examples of complex rendering, see the source code for ``{% if %}``, ``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in -``django/core/template/defaulttags.py``. +``django/template/defaulttags.py``. |
