On 26/02/17 00:44, Karen Tracey wrote:
On Sat, Feb 25, 2017 at 2:10 PM, Tim Graham <[email protected]
<mailto:[email protected]>> wrote:
I think any use of undefined template variables should raise an
exception. In the long run, keeping a setting to allow some other
behavior seems confusing and, considering the case of templates
that might be reused in different projects with different
settings, even dangerous.
I think I'm confused...Django templates have allowed use of undefined
variables and documented their use as evaluating to the empty string
for as long as I recall. Wouldn't a change to instead raise exceptions
be a major backwards-incompatibility?
https://docs.djangoproject.com/en/1.7/topics/templates/#variables said
"If you use a variable that doesn’t exist, the template system will
insert the value of the TEMPLATE_STRING_IF_INVALID setting, which is
set to '' (the empty string) by default."
This behaviour applies only to what happens when the variable is
rendered. In the context of `if` tags, undefined variables get converted
to `None`. This behaviour is documented -
https://docs.djangoproject.com/en/dev/ref/templates/api/#how-invalid-variables-are-handled
but perhaps not in as much detail as necessary.
The question is about changing this, especially due to templates like this:
{% if user.role == roles.staff %}
[sensitive information here]
{% endif %}
If:
1) you forget to provide both user and role to template context or
2) 'role' or 'staff' are invalid attributes, or
3) 'role' returns None but 'staff' is an invalid attribute, for example,
4) various combinations of these
then this results in the sensitive info being shown, because `None ==
None`. The proposal is to introduce a value that doesn't not compare
equal to itself and avoid this kind of issue.
Having thought about it more, I've realised that this really isn't going
to work at all.
First attempt:
class Undefined1(object):
def __eq__(self, other):
return False
If we use this, then consider the following template code:
{% if user.role != roles.staff %}
This info is private, sorry
{% else %}
[sensitive information here]
{% endif %}
The default implementation of != means we will again get the sensitive
data shown for some of the error situations given above (e.g. 1 and 2).
Second attempt:
class Undefined2(object):
def __eq__(self, other):
return False
def __new__(self, other):
return False
This object is neither equals nor not-equals to itself or anything else.
But consider this template:
{% if user.role == roles.customer %}
This info is private, sorry
{% else %}
[sensitive information here]
{% endif %}
With `Undefined2` being used for invalid attributes, we again get the
sensitive information being shown in the case of developer error and
missing attributes. Plus, we now have the situation that `{% if a != b
%}` is not the same as `{% if not a == b %}`, which is very confusing
behaviour for most people.
In other words, we are getting into the territory of needing a value
that behaves like NULL in SQL. Even if there were no implementation
issues (and there will be lots, because operators like 'or' 'and' etc.
would need to cope with this, not to mention 3rd party code), and there
were no backwards compatibility issues (there are lots), this would be
extremely dubious to me, because ternary logic is extremely tricky.
The only sensible alternative to current behaviour is to raise
exceptions, but huge backwards incompatibility issues I think rule this
out. If I were to start again, I think I would make the template system
not silence any errors you would normally get in Python, but just have
some special syntax for converting non-existent data or attributes into
None. But I don't have that time machine.
Regards,
Luke
--
You received this message because you are subscribed to the Google Groups "Django
developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/4b0a8ec9-c588-de8d-76ba-0d3b55b8fe20%40cantab.net.
For more options, visit https://groups.google.com/d/optout.