Fixed #15057 - documented change in [14992]
Thanks to Tai Lee for the patch. Refs #15025, #7153 git-svn-id: http://code.djangoproject.com/svn/django/trunk@15188 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
80f4826063
commit
7b8c38250c
|
@ -415,9 +415,9 @@ like:
|
||||||
|
|
||||||
The template system uses dot-lookup syntax to access variable attributes. In
|
The template system uses dot-lookup syntax to access variable attributes. In
|
||||||
the example of ``{{ poll.question }}``, first Django does a dictionary lookup
|
the example of ``{{ poll.question }}``, first Django does a dictionary lookup
|
||||||
on the object ``poll``. Failing that, it tries attribute lookup -- which works,
|
on the object ``poll``. Failing that, it tries an attribute lookup -- which
|
||||||
in this case. If attribute lookup had failed, it would've tried calling the
|
works, in this case. If attribute lookup had failed, it would've tried a
|
||||||
method ``question()`` on the poll object.
|
list-index lookup.
|
||||||
|
|
||||||
Method-calling happens in the ``{% for %}`` loop: ``poll.choice_set.all`` is
|
Method-calling happens in the ``{% for %}`` loop: ``poll.choice_set.all`` is
|
||||||
interpreted as the Python code ``poll.choice_set.all()``, which returns an
|
interpreted as the Python code ``poll.choice_set.all()``, which returns an
|
||||||
|
|
|
@ -115,18 +115,15 @@ Variable names must consist of any letter (A-Z), any digit (0-9), an underscore
|
||||||
or a dot.
|
or a dot.
|
||||||
|
|
||||||
Dots have a special meaning in template rendering. A dot in a variable name
|
Dots have a special meaning in template rendering. A dot in a variable name
|
||||||
signifies **lookup**. Specifically, when the template system encounters a dot
|
signifies a **lookup**. Specifically, when the template system encounters a
|
||||||
in a variable name, it tries the following lookups, in this order:
|
dot in a variable name, it tries the following lookups, in this order:
|
||||||
|
|
||||||
* Dictionary lookup. Example: ``foo["bar"]``
|
* Dictionary lookup. Example: ``foo["bar"]``
|
||||||
* Attribute lookup. Example: ``foo.bar``
|
* Attribute lookup. Example: ``foo.bar``
|
||||||
* Method call. Example: ``foo.bar()``
|
|
||||||
* List-index lookup. Example: ``foo[bar]``
|
* List-index lookup. Example: ``foo[bar]``
|
||||||
|
|
||||||
The template system uses the first lookup type that works. It's short-circuit
|
The template system uses the first lookup type that works. It's short-circuit
|
||||||
logic.
|
logic. Here are a few examples::
|
||||||
|
|
||||||
Here are a few examples::
|
|
||||||
|
|
||||||
>>> from django.template import Context, Template
|
>>> from django.template import Context, Template
|
||||||
>>> t = Template("My name is {{ person.first_name }}.")
|
>>> t = Template("My name is {{ person.first_name }}.")
|
||||||
|
@ -141,26 +138,34 @@ Here are a few examples::
|
||||||
>>> t.render(Context({"person": p}))
|
>>> t.render(Context({"person": p}))
|
||||||
"My name is Ron."
|
"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 }}.")
|
>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
|
||||||
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
|
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
|
||||||
>>> t.render(c)
|
>>> t.render(c)
|
||||||
"The first stooge in the list is Larry."
|
"The first stooge in the list is Larry."
|
||||||
|
|
||||||
Method lookups are slightly more complex than the other lookup types. Here are
|
If any part of the variable is callable, the template system will try calling
|
||||||
some things to keep in mind:
|
it. Example::
|
||||||
|
|
||||||
* If, during the method lookup, a method raises an exception, the exception
|
>>> class PersonClass2:
|
||||||
will be propagated, unless the exception has an attribute
|
... def name(self):
|
||||||
|
... return "Samantha"
|
||||||
|
>>> t = Template("My name is {{ person.name }}.")
|
||||||
|
>>> t.render(Context({"person": PersonClass2}))
|
||||||
|
"My name is Samantha."
|
||||||
|
|
||||||
|
.. versionchanged:: 1.3
|
||||||
|
Previously, only variables that originated with an attribute lookup would
|
||||||
|
be called by the template system. This change was made for consistency
|
||||||
|
across lookup types.
|
||||||
|
|
||||||
|
Callable variables are slightly more complex than variables which only require
|
||||||
|
straight lookups. Here are some things to keep in mind:
|
||||||
|
|
||||||
|
* If the variable raises an exception when called, the exception will be
|
||||||
|
propagated, unless the exception has an attribute
|
||||||
``silent_variable_failure`` whose value is ``True``. If the exception
|
``silent_variable_failure`` whose value is ``True``. If the exception
|
||||||
*does* have a ``silent_variable_failure`` attribute, the variable will
|
*does* have a ``silent_variable_failure`` attribute whose value is
|
||||||
render as an empty string. Example::
|
``True``, the variable will render as an empty string. Example::
|
||||||
|
|
||||||
>>> t = Template("My name is {{ person.first_name }}.")
|
>>> t = Template("My name is {{ person.first_name }}.")
|
||||||
>>> class PersonClass3:
|
>>> class PersonClass3:
|
||||||
|
@ -187,12 +192,12 @@ some things to keep in mind:
|
||||||
with Django model objects, any ``DoesNotExist`` exception will fail
|
with Django model objects, any ``DoesNotExist`` exception will fail
|
||||||
silently.
|
silently.
|
||||||
|
|
||||||
* A method call will only work if the method has no required arguments.
|
* A variable can only be called if it has no required arguments. Otherwise,
|
||||||
Otherwise, the system will move to the next lookup type (list-index
|
the system will return an empty string.
|
||||||
lookup).
|
|
||||||
|
|
||||||
* Obviously, some methods have side effects, and it'd be either foolish or
|
* Obviously, there can be side effects when calling some variables, and
|
||||||
a security hole to allow the template system to access them.
|
it'd be either foolish or a security hole to allow the template system
|
||||||
|
to access them.
|
||||||
|
|
||||||
A good example is the :meth:`~django.db.models.Model.delete` method on
|
A good example is the :meth:`~django.db.models.Model.delete` method on
|
||||||
each Django model object. The template system shouldn't be allowed to do
|
each Django model object. The template system shouldn't be allowed to do
|
||||||
|
@ -200,8 +205,8 @@ some things to keep in mind:
|
||||||
|
|
||||||
I will now delete this valuable data. {{ data.delete }}
|
I will now delete this valuable data. {{ data.delete }}
|
||||||
|
|
||||||
To prevent this, set a function attribute ``alters_data`` on the method.
|
To prevent this, set an ``alters_data`` attribute on the callable
|
||||||
The template system won't execute a method if the method has
|
variable. The template system won't call a variable if it has
|
||||||
``alters_data=True`` set. The dynamically-generated
|
``alters_data=True`` set. The dynamically-generated
|
||||||
:meth:`~django.db.models.Model.delete` and
|
:meth:`~django.db.models.Model.delete` and
|
||||||
:meth:`~django.db.models.Model.save` methods on Django model objects get
|
:meth:`~django.db.models.Model.save` methods on Django model objects get
|
||||||
|
|
|
@ -392,7 +392,23 @@ if you need to instantiate an empty ``FormSet``, don't pass in the data or use
|
||||||
>>> formset = ArticleFormSet()
|
>>> formset = ArticleFormSet()
|
||||||
>>> formset = ArticleFormSet(data=None)
|
>>> formset = ArticleFormSet(data=None)
|
||||||
|
|
||||||
|
Callables in templates
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Previously, a callable in a template would only be called automatically as part
|
||||||
|
of the variable resolution process if it was retrieved via attribute
|
||||||
|
lookup. This was an inconsistency that could result in confusing and unhelpful
|
||||||
|
behaviour::
|
||||||
|
|
||||||
|
>>> Template("{{ user.get_full_name }}").render(Context({'user': user}))
|
||||||
|
u'Joe Bloggs'
|
||||||
|
>>> Template("{{ full_name }}").render(Context({'full_name': user.get_full_name}))
|
||||||
|
u'<bound method User.get_full_name of <...
|
||||||
|
|
||||||
|
This has been resolved in Django 1.3 - the result in both cases will be ``u'Joe
|
||||||
|
Bloggs'``. Although the previous behaviour was not useful for a template language
|
||||||
|
designed for web designers, and was never deliberately supported, it is possible
|
||||||
|
that some templates may be broken by this change.
|
||||||
|
|
||||||
.. _deprecated-features-1.3:
|
.. _deprecated-features-1.3:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue