Format floats in Django template in language aware manner - django

I am using Django's humanize to make large float numbers in my app more readable. Also my app is available in different languages, and different languages use , and . signs in numbers the other way around.
For integer values the humanize tag intcomma works well:
{{ intvalue|intcomma }}
Would give for different locales:
English: 1,000,000
Dutch: 1.000.000
However, using floats this doesn't work very well. For example in my template you would find this:
{{ floatvalue|floatformat:2|intcomma }}
Would give for different locales:
English: 1,000,000.00
Dutch: 1,000,000,00
Note that instead of 1.000.000,00 for Dutch, it shows 1,000,000,00. Switching around the floatformat:2 and intcomma tags doesn't work either as then the value is nothing.
Any ideas on how to easily fix this?
(If possible, I'd rather not use an external libraries such as Babel)

Try the Django Format Localization feature. It gives you three options. As the Django docs say,
Django’s formatting system is capable to display dates, times and numbers in templates using the format specified for the current locale. It also handles localized input in forms.
When it’s enabled, two users accessing the same content may see dates, times and numbers formatted in different ways, depending on the formats for their current locale.
The formatting system is disabled by default. To enable it, it’s necessary to set USE_L10N = True in your settings file.
Thus this first option turns on locale-dependent number formatting for all of your templates.
A second option is to use the localize template tag to turn on locale-dependent number formatting for only part of a template. For example,
{% load l10n %}
{% localize on %}
{{ value }}
{% endlocalize %}
A third option is to use the localize template filter to force locale-dependent number formatting for a single value. For example,
{% load l10n %}
{{ value|localize }}

Related

String manipulation in Django templates

Imagine the context variable {{ url }} outputs www.example.com/<uuid-string> where <uuid-string> is different every time, whereas the former part of the URL stays the same.
Can one change the output of {{ url }} to instead www.forexample.com/<uuid-string>, via solely manipulating the string in the template and without involving views.py (which I know is the better way to do it, but that's not the question).
An illustrative example would be great.
read about filters and templatetags - they are a methods that allows you to perform some actions on variables in templates.
You can also create your own tags and filters that allow you to perform action non-built into Django template language
Simple example of such filter:
#in templatetags.py
#register.filter(name='duplicate')
def duplicate(value):
return value*2
#in your template
<p> {{ url|duplicate }} </p>
You can find more examples here. Also there you will find tutorial how to use and create them

How django's template tag "include" work with None

I'm using an include tag in my templates like this:
{% include fragment_variable %}
where fragment_variable is a context variable that might not exist. I wonder if it will blow up when fragment_variable is not in context variables or is None.
NOTE: actually I tested this code in two different environments (both using Django 1.7) and got two different results (one blew up with some stack trace for templates lookups and the other just failed silently). So I'm curious if there's a setting in django that controls how template rendering behaves when "include" tag can't find a valid template.
{% if fragment_variable %}
{% include fragment_variable %}
{% else %}
<!-- something else -->
{% endif %}
Edit:
Since you are using django version prior to 1.8, take a look at the setting TEMPLATE_STRING_IF_INVALID, it sets the default value for invalid variables.
Also take a look at How invalid variables are handled:
Generally, if a variable doesn’t exist, the template system inserts
the value of the engine’s string_if_invalid configuration option,
which is set to '' (the empty string) by default.
This behavior is slightly different for the if, for and regroup
template tags. If an invalid variable is provided to one of these
template tags, the variable will be interpreted as None. Filters are
always applied to invalid variables within these template tags.
For that matter, I still consider using if is the best exercise.

Is using the "escape" tag really mandatory as a good security pattern in Django?

In the security chapter of The Django Book, it says that I must always use the template tag {% escape %} in order to protect my site from cross-site scripting.
Is it really necessary to put the escape tag on every single template string? Is there a way to specify this at application level?
That version of the Django book was written well before 1.0 came out, and is significantly out of date. All template content has been autoescaped for quite some time now.
In django is been done automatically. To turn it off you have to use the autoescape tag. I'm not sure since when, but at least since 1.1 version.
{% autoescape off %}
safe stuff
{% endautoscape %}

Is is possible to html encode output in AppEngine templates?

So, I'm passing an object with a "content" property that contains html.
<div>{{ myobject.content }}</div>
I want to be able to output the content so that the characters are rendered as the html characters.
The contents of "conent" might be: <p>Hello</p>
I want this to be sent to the browser as: &amplt;p&ampgt;Hello&amplt;/p>
Is there something I can put in my template to do this automatically?
Yes, {{ myobject.content | escape }} should help (assuming you mean Django templates -- there's no specific "App Engine" templating system, GAE apps often use the Django templating system); you may need to repeat the | escape part if you want two levels of escaping (as appears to be the case in some but not all of the example you supply).
This is Django's django.utils.html.escape function:
def escape(html):
"""Returns the given HTML with ampersands, quotes and carets encoded."""
return mark_safe(force_unicode(html).replace('&', '&').replace('<', '&l
t;').replace('>', '>').replace('"', '"').replace("'", '''))
Also, see here.

Is there any reason why you can't compare a template filter to a string in Django template syntax?

I'm trying to do this, and failing. Is there any reason why it wouldn't work in Django template syntax? I'm using the latest version of Django.
{% ifequal entry.created_at|timesince "0 minutes" %}
It doesn't work because it's not supposed to work. What you're asking for is not part of the template language.
You can't apply a filter in the middle of tag like {% ifequal. When a template tag uses a variable, it doesn't expect an expression, it expects a variable, nothing more.
That kind of logic -- extracting time since, comparing, etc. -- is what you're supposed to do in your view function.
Your view function then puts a "zerominutes" item in the context for the template to use. Templates just can't do much processing.
They're designed to do the minimum required to render HTML. Everything else needs to be in your view function.
{% ifequal %} tag doesn't support filter expressions as arguments. It treats whole entry.created_at|timesince as identifier of the variable.
Quik workaround: introduce intermediate variable with expresion result using {% with %} like this:
{% with entry.created_at|timesince as delta %}
{% ifequal delta "0 minutes" %}
....
{% endifequal %}
{% endwith %}
See ticket #5756 and links in its comments for more information. A patch for Django in ticket #7295 implements this functionality. A broader refactoring of the template system based on #7295 is proposed in ticket #7806, and it would fix this issue among others.
I don't think making such comparisons to work would be against the design philosophy of Django templates.
I think you can, though I don't see any uses of it my code base. Maybe entry.created_at|timesince isn't producing the value you expect. Try putting
X{{entry.created_at|timesince}}X
into your template and seeing what value it produces. The X's are so you can see leading or trailing space, in case that is the problem.
I finally gave up on using the Django template language for anything other than the simplest pages. Check out Jinja2 for an almost-syntax-compatible alternative. And yes, you can choose which to use on a page-by-page basis.