How to limit jinja2 logic? - python

I'd like to use jinja2 for rendering strings like "Value is {{ obj.value }}".
I only want to allow substituting template variables = the {{ }} syntax.
I do not want to allow any logic whatsoever = the {% %} syntax.
How do I make jinja2 rendering "less powerful" to achieve this?
Security concerns? Note that while these templates are to be input by the user, the rendered output will be rendered via jinja2 again, as part of an HTML template. So characters like < and > will be escaped before becoming HTML as sent to the browser.

Related

How to let Jinja bypass MathJax symbols [duplicate]

I serve dynamic pages from Jinja2 templates in Flask. Now I am defining client-side templates in say, Jinja2-clone Nunjucks inside a script tag. Problem is, the client-side templates has syntax like <% %> that Flask's Jinja2 interpreter may interpret instead of rendering verbatim.
How can I make the entire block of scripts render verbatim?
You can disable interpretation of tags inside a {% raw %} block:
{% raw %}
Anything in this block is treated as raw text,
including {{ curly braces }} and
{% other block-like syntax %}
{% endraw %}
See the Escaping section of the template documentation.

How I do convert an md file to HTML and pass the variable into HTML file [duplicate]

Is there any way to completely turn off django auto_escaping when rendering a template within the view code (for an email for example):
from django.template import Context, Template
subject_template_string = "Hi {{ customer.name }}"
subject_template = Template(subject)
context = Context({'customer':MyCustomerModel.objects.get(pk=1)})
subject = subject_template.render(context)
If customer.name is something like "Jack & Jill" - the subject looks like "Hi Jack &\amp; Jill" (without the backslash!)
is there something like
subject = subject_template.render(context, autoescape=False)
edit: The actual templates are created by the client in the database, I'm hoping to avoid having to say add |safe to all templates where this might happen...
Disabling it globally is usually a bad idea since you can easily forget it. I would recommend using the templatetag to disable it for that portion of your template instead.
Something like this:
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
How about using mark_safe:
Explicitly mark a string as safe for (HTML) output purposes. The
returned object can be used everywhere a string or unicode object is
appropriate.
It marks a string as safe, so, you should take customer.name out and pass to the template:
from django.utils.safestring import mark_safe
customer = MyCustomerModel.objects.get(pk=1)
context = Context({'customer_name': mark_safe(customer.name)})
subject = subject_template.render(context)
Though, control what is safe or not is better to do inside the template itself, that's why using autoescape should be preffered.
Use Django's autoescape tag:
{% autoescape off %}
{{ body }}
{% endautoescape %}
for more info, check out the docs here.
This is untested, but based on source code review it looks like the context object can take autoescape as a key.
context = Context({'customer':MyCustomerModel.objects.get(pk=1), 'autoescape': False})
subject = subject_template.render(context)
That said, that's a pretty sweeping change. If you know what values the templates might be looking for, it's probably better to use mark_safe on those values and pass in the predefined options. That would have the added benefit of not risking the possibility of the client template calling a method with side effects on the customer. The first time someone writes a template and puts in {{ customer.delete }}, you have a problem.
Just came back to answer my own question with a simple solution, and there were already 4 answers.. thanks.
This is what I've gone with:
subject_template = Template(u'{%% autoescape off %%}%s{%% endautoescape %%}' % email.subject)

How can I use Django intcomma in integerfield

I'd like to separate numerical values in the form with a comma in my Django project.
Then I found the documentation below:
https://docs.djangoproject.com/en/2.0/ref/contrib/humanize/
I thought that I can use 'intcomma' for my purpose. So I added "django.contrib.humanize" to my INSTALLED_APPS setting. And put {% load humanize %} in a template.
When I use 'intcomma' like below, it worked.
{{ 999999|intcomma }} # 999,999
But It did not work for integer form like below:
{{ form.numbers|intcomma }} # did not work.
A code was displayed to html instead of numbers like this:
<input type="number" name="int_sample" value="100000" id="id_int_sample"
My Django version is 2.0.1.
Formatting the value of an IntegerField
You access the value of an IntegerField with the .value attribute, so:
{{ form.numbers.value|intcomma }}
Note that this is the value set to the Form when you construct it. For example through initial={..} or the value that corresponds to the instance=... you pass to the field. If you for example in th form change the value, the content will not change.
Generating an <input> with number formatting
In case we want the <input> element itself to format the number separated with comma's, we will need some HTML/JavaScript. Since Django basically only renders a webpage. How the webpage behaves in the browser is not really the responsibility of Django.
We can for example use the following approach:
<script language="JavaScript">
function commas(input){
input.value = Number(input.value).toLocaleString();
}
</script>
{{ form.numbers }}
And the Form should then make sure the commas function is invoked:
SomeForm(forms.Form):
numbers = forms.IntegerField(
widget=forms.TextInput(attrs={'onclick':'commas(self)'})
)

Django models - html/render attribute?

I use the same models in many different templates and tables. I'm looking for a way to tell Django how to render those objects in templates so I don't have to write the same html again and again.
For example model Url - when I want to display it inside a template or table, I have to write (sometimes much more):
{{ url.site.name }}
which renders:
Stackoverflow.com
It would be better if I could just do something like:
{{ url }} # url is Url model object
I think that I can add methods like def render_object(self) like this:
def render_object(self):
return mark_safe("""{}""".format(self.url,self.site.name))
and in templates:
{{ url.render_object }}
but I'm curious if it is there some built in function. As far as I know __unicode__(self) would do the work but it would mess admin and shell display names.
Add custom template tag my_tags.py like render_url and then in your template load that template tag ({% load my_tags %}) and send url object to it: {% render_url url %}. You can use html template in your tag or just make result as a string and return it. Check the documentation for details.

How to escape {{ or }} in django template?

Django treats {{ var }} as some variable in its template. How can I escape {{ var }} or {{ or }} such that django does not treat it as variable.
<p>"{{ some text }}"</p> Should prints exactly the same.
Django 1.5 introduced {% verbatim %} template tag. It stops template from parsing contents of this tag:
{% verbatim %}
{{ var }}
{% endverbatim %}
will be rendered as:
{{ var }}
I believe you are looking for the templatetag template tag.
As the linked-to doc states,
Since the template system has no concept of "escaping", to display one of the bits used in template tags, you must use the {% templatetag %} tag.
For example:
<p>"{% templatetag openvariable %} some text {% templatetag closevariable %}"</p>
will appear as so:
<p>"{{ some text }}"</p>
Edit: I don't really recommended this because it's not very clean, but it's still an option.
I was searching for one that I could use with JQuery Templates and figured a way to do it without tags or filters. This is as short as I could get it:
{{ "{{ any text }" }}}
Is printed as:
{{ any text }}
Why it works? Any text within {{}} is displayed as is, as long as it doesn't have two closing braces }} in a row. Then there are three brackets in a row, django interprets two first ones as end of the variable leaving one additional closing brace.
You can try escaping with html character escapes like:
{ = {
} = }
<p>"{{ some text }}"</p>
Update
In case anyone is trying to use the actual tags for javascript, verbatim is a better solution:
Stops the template engine from rendering the contents of this block tag.
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
if you simply need to use {{ }} as a variable for template framework like angularjs, then following maybe simpler:
in your <app path>/templatetags/ngvar.py , add
from django import template
register = template.Library()
#register.simple_tag
def ngvar(var_name):
return "{{%s}}" % var_name
and in template, do
{% load ngvar %}
{% ngvar "variable name" %}
if ngvar.py is the first template tag, then make sure to add __init__.py file to the templatetags directory
Another option would be to add a word joiner (zero width no-break space) between each curly bracket:
<p>"{⁠{ some text }⁠}"</p>
Although the above answers can solve the original problem, I add some hack around here for those who are scratching their heads like me.
Some times, we want to render a single brace followed by a variable. For example, in BibTeX, there may be something look like this:
#MISC{hu2012-spectral,
author = {Hu, Pili},
title = {Spectral Clustering Survey},
howpublished = {GitHub, https://github.com/hupili/tutorial/tree/master/spectral-clustering},
month = {May},
year = {2012}
}
Those bib fields come from template variables. If you write
title = {{{title}}},
jinja can not compile and raise an error. If you write
title = { {{title}} },
there will be extra blanks. The hack around is to store '{' and '}' as variables and use later.
{% set lb = '{' %}
{% set rb = '}' %}
...
#MISC{{lb}}{{ meta.bib_key }},
author = {{lb}}Hu, Pili{{rb}},
title = {{lb}}{{ meta.title }}{{rb}},
howpublished = {{lb}}GitHub, https://github.com/hupili/tutorial/tree/master/{{ auto.path}}{{rb}},
month = {{lb}}{{ meta.month }}{{rb}},
year = {{lb}}{{ meta.year }}{{rb}}
}
This looks clumsy but it is the best I find so far. If you have a cleaner solution, please tell me.
This template tag (designed for use with jQuery Templates) might do the trick. It let's you wrap content you don't want Django to interpret as variables with a template tag.
it can be solved by avoing adjacent angular backets, if its inside javascript code then you can write
'{'+'{address.'+key+'}}'
I used this to print jinja variables into another template,using javascript.
Jinja, which is what is being used for the templates, offers several suggestions for escaping here. What has worked best for me is using something like "{% raw %}{{ some text }}{% endraw %}"

Categories

Resources