& g t ; Welcome
How do I show the actual symbol instead? Is it a template filter?
Thanks.
Bit hard to know without more details. If it's from data that you're passing in from the view, you might want to use mark_safe.
from django.utils.safestring import mark_safe
def your_view(request):
...
foo = '>'
mark_safe(foo)
...
Otherwise, you want the safe filter:
{{ myvar|safe }}
Obviously, be careful with this, make sure the variable actually is safe, otherwise you'll open yourself up to cross-site scripting attacks and the like. There's a reason Django escapes this stuff.
Related
I know that sessions are available through html templates like so:
<h1>{{session.name}}</h1>
That worked for a while but when I wanted to add more attributes to a user like an about text, I couldn't store everything in the session. The email and password I do store in the session because they are actually used. I can retrieve a user with the email and get the name like so:
User.query.filter_by(email=session['email']).first().name
However, when I try putting it into html like this it says that Users is undefined.
<li>Name: {{Users.query.filter_by(email=session['email']).first().name}}</li>
I guess some things like that are not carried over but is there a straightforward way to get all variables from the main.py file I was using there?
I even tried doing
return redirect(url_for('user', \
usr=Users.query.filter_by(email=session['email']).first().__dict__))
in main.py and then doing
<li class="list-group-item">Name: {{usr['name']}}</li>
but that wouldn't work either for some reason. What is going on?
The first solution I tried doesn't work because Flask doesn't have a reference to Users. The second doesn't work either because I passed it through url_for and not the actual render template function so it wouldn't know what to do with it.
My final solution would be this:
usr = Users.query.filter_by(email=session['email']).first().__dict__
return render_template('user.html', name=usr['name'], status=usr['status'],
about=usr['about'])
I could also just have passed the entire dict as before I believe.
I'm looking for an idiom for setting some common item definitions so that any time I call render() on a mako template, those items will be added to the parameters available in the template without having to include them in the parameters to render() each time.
The example at http://docs.makotemplates.org/en/latest/usage.html suggests that the place I should be looking is in some way of either setting some master Context definitions or something, or perhaps a way of merging two contexts:
from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO
mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print(buf.getvalue())
I can't find anything explicitly showing an example of doing this, and poking around in dir(Context) isn't making anything come to mind. Is this a simple thing to do and I'm just overlooking the obvious? Or is there a standard idiom for this?
Thanks in advance!
Update: I suppose one approach is to explicitly append **kwargs to each call to render(), and that's not bad, as it's explicit:
template = self.template_lookup.get_template("index.mako.html")
return template.render(var1=val1, var2=val2, **common_vars)
Still curious if there's a way to "fully predefine" such items.
When I was trying to access a tuple inside a list in the Django template format, I found out I couldn't access it with a[ 0 ][ 1 ], instead I had to use a.0.1.
Suppose that a is something like
a = [
( 'a', 'apple' ),
( 'b', 'bee' ),
]
Why doesn't Django template language support a[ 0 ][ 1 ]? In normal Python programming, a.0.1 would give you a syntax error.
The Django docs on the template API explain this nicely:
Dots have a special meaning in template rendering. A dot in a variable name signifies a 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
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.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."
>>> 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."
Variable._resolve_lookup in django.templates.base appears to be the function responsible for this, and hasn't changed much since the oldest revision I can find
You can find some information about this in the django book:
The beginning of the chapter should explain why it works this way:
In the previous chapter, you may have noticed something peculiar in how we returned the text in our example views. Namely, the HTML was hard-coded directly in our Python code, like this:
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
Although this technique was convenient for the purpose of explaining how views work, it’s not a good idea to hard-code HTML directly in your views. Here’s why:
Any change to the design of the page requires a change to the Python code. The design of a site tends to change far more frequently than the underlying Python code, so it would be convenient if the design could change without needing to modify the Python code.
Writing Python code and designing HTML are two different disciplines, and most professional Web development environments split these responsibilities between separate people (or even separate departments). Designers and HTML/CSS coders shouldn’t be required to edit Python code to get their job done.
It’s most efficient if programmers can work on Python code and designers can work on templates at the same time, rather than one person waiting for the other to finish editing a single file that contains both Python and HTML.
For these reasons, it’s much cleaner and more maintainable to separate the design of the page from the Python code itself. We can do this with Django’s template system, which we discuss in this chapter.
...
Dot lookups can be summarized like this: when the template system encounters a dot in a variable name, it tries the following lookups, in this order:
Dictionary lookup (e.g., foo["bar"])
Attribute lookup (e.g., foo.bar) 1
Method call (e.g., foo.bar())
List-index lookup (e.g., foo[2])
The system uses the first lookup type that works. It’s short-circuit logic.
The reason I would say that the django template language doesnt do XYZ way of accessing context data is because generally at that point you are doing too much in the template side vs your view that renders it.
The design decision of their template engine seems lighter than maybe some others which give you more pythonic direct access to data. But ideally you would be formatting th context before passing it in.
You also have the ability to create your own template filters for doing more custom processing of data.
Specific to your question, accesing child members using dot notation is the django template way to try multiple approaches to resolving the member. It tries dictionary keys, attributes, etc. in a certain order. You just use dot notation for everything.
In the docs it says:
The only exceptions are variables that are already marked as “safe” from escaping, either by the code that populated the variable, or because it has had the safe or escape filters applied."
How does the "populated the variable" part work ? I'm actually looking for a way to declare a template tag as safe in the view. I somehow think it's not a good idea to let a designer decide. My co-worker will just add it whenever she 'thinks' it's a good idea.
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs
Django has a subclass of strings called safe strings (specifically SafeUnicode or SafeString), which can be created using django.utils.safestring.mark_safe. When the template engine comes across a safe string it doesn't perform HTML escaping on it:
>>> from django.utils.safestring import mark_safe
>>> from django.template import Template, Context
>>> Template("{{ name }}").render(Context({'name': mark_safe('<b>Brad</b>')}))
u"<b>Brad</b>"
If you're writing your own template tag, you need to implement render() which will return a string that will be treated as safe, meaning you have to handle any escaping necessary yourself. However if you're writing a template filter, you can set the attribute is_safe = True on the filter to avoid auto escaping of the returned value, e.g.
#register.filter
def myfilter(value):
return value
myfilter.is_safe = True
See https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/#filters-and-auto-escaping for more details.
You could call django.utils.safestring.mark_safe and pass you variable
...
return direct_to_template('my-template.html', {'safe_var': mark_safe('<script>alert("");</script>')})
In template it will be printed without escaping (alert will popup). Though auto-escape is really a great feature that will save you from some bad things.
Using {{today|time:"TIME_FORMAT"}} correctly localises times when I switch languages in my Django 1.2.3 project. E.g. for English I see "12:19 a.m." and when I switch to German it changes to "12:19:25".
As far as I can tell from looking at the docs and code (defaultfilters.py and formats.py) just using {{today:time}} should do the same thing and default to TIME_FORMAT but this isn't working and it always uses the default English format.
Is there a way to avoid having to edit all my templates and change them to {{today|time:"TIME_FORMAT"}}?
The same thing happens with the date filter and DATE_FORMAT.
The docs say (emphasis mine):
When used without a format string:
{{ value|time }}
...the formatting string defined in the TIME_FORMAT setting will be used, without applying any localization.
You have two options:
Edit all your templates to make the change, or
Create a new filter of your own that does it the way you want.
Thanks #Ned Batchelder, as per option 2., I've added the following to my custom template tags file:
from django.template.defaultfilters import date as defaultfilters_date, time as defaultfilters_time
# FORCE {{...|date}} to be equivalent to {{...|date:"DATE_FORMAT"}} so it localizes properly, ditto for time and TIME_FORMAT
#register.filter(name="date")
def date_localized(val, arg=None):
return defaultfilters_date(val, arg or "DATE_FORMAT")
#register.filter(name="time")
def time_localized(val, arg=None):
return defaultfilters_time(val, arg or "TIME_FORMAT")