Formatting TimeField in Django template shows nothing - django

I have a model that includes a TimeField object. I also have a django template that lists the time field in JSON Format
e.g.
...
"time":"{{ mymodel.mytime }}",
...
Without specifying any formatting/filters etc, this results in the following e.g.
....
"time":"5 p.m.",
....
However when I apply a time filter to my template i.e.
...
"time":"{{ mymodel.mytime|time:"H:i" }}",
...
I get the following result:
...
"time":"",
...
i.e. my time value is wiped out. I am not sure what's going on? I also have a datefield in the same model and the filter I am applying to that (in the same django template) which works as defined.
I am using Django 1.4.2
What am I missing or not doing correctly?

You have put time format in double quotes too.
try:
"time":"{{ mymodel.mytime|time:'H:i' }}",
or
"time":'{{ mymodel.mytime|time:"H:i" }}',
or
"time":"{{ mymodel.mytime|time:\"H:i\" }}",

time
Formats a time according to the given format.
Given format can be the predefined one TIME_FORMAT, or a custom format, same as the date filter. Note that the predefined format is locale-dependent.
For example:
{{ value|time:"H:i" }}

For some bizzare reason, not sure what.. It has started working! Must have been a typo or something in the filter format?! Really weird.

Related

Using date filter in Jinja2 template raises TemplateSyntaxError [duplicate]

Using Jinja2, how do I format a date field? I know in Python I can simply do this:
print(car.date_of_manufacture.strftime('%Y-%m-%d'))
But how do I format the date in Jinja2?
There are two ways to do it. The direct approach would be to simply call (and print) the strftime() method in your template, for example
{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}
Another, sightly better approach would be to define your own filter, e.g.:
from flask import Flask
import babel
app = Flask(__name__)
#app.template_filter()
def format_datetime(value, format='medium'):
if format == 'full':
format="EEEE, d. MMMM y 'at' HH:mm"
elif format == 'medium':
format="EE dd.MM.y HH:mm"
return babel.dates.format_datetime(value, format)
(This filter is based on babel for reasons regarding i18n, but you can use strftime too). The advantage of the filter is, that you can write
{{ car.date_of_manufacture|format_datetime }}
{{ car.date_of_manufacture|format_datetime('full') }}
which looks nicer and is more maintainable. Another common filter is also the "timedelta" filter, which evaluates to something like "written 8 minutes ago". You can use babel.dates.format_timedelta for that, and register it as filter similar to the datetime example given here.
Here's the filter that I ended up using for strftime in Jinja2 and Flask
#app.template_filter('strftime')
def _jinja2_filter_datetime(date, fmt=None):
date = dateutil.parser.parse(date)
native = date.replace(tzinfo=None)
format='%b %d, %Y'
return native.strftime(format)
And then you use the filter like so:
{{car.date_of_manufacture|strftime}}
I think you have to write your own filter for that. It's actually the example for custom filters in the documentation.
If you are dealing with a lower level time object (I often just use integers), and don't want to write a custom filter for whatever reason, an approach I use is to pass the strftime function into the template as a variable, where it can be called where you need it.
For example:
import time
context={
'now':int(time.time()),
'strftime':time.strftime } # Note there are no brackets () after strftime
# This means we are passing in a function,
# not the result of a function.
self.response.write(jinja2.render_template('sometemplate.html', **context))
Which can then be used within sometemplate.html:
<html>
<body>
<p>The time is {{ strftime('%H:%M%:%S',now) }}, and 5 seconds ago it was {{ strftime('%H:%M%:%S',now-5) }}.
</body>
</html>
You can use it like this in template without any filters
{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}
Google App Engine users : If you're moving from Django to Jinja2, and looking to replace the date filter, note that the % formatting codes are different.
The strftime % codes are here: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior
You can use it like this in jinja template
{{ row.session_start_date_time.strftime('%d-%m-%Y %H:%M:%S')}}
In this code the field name is row.session_start_date_time.
in flask, with babel, I like to do this :
#app.template_filter('dt')
def _jinja2_filter_datetime(date, fmt=None):
if fmt:
return date.strftime(fmt)
else:
return date.strftime(gettext('%%m/%%d/%%Y'))
used in the template with {{mydatetimeobject|dt}}
so no with babel you can specify your various format in messages.po like this for instance :
#: app/views.py:36
#, python-format
msgid "%%m/%%d/%%Y"
msgstr "%%d/%%m/%%Y"
I use this filter, it's in Spanish but you may change the names as you need.
#app.template_filter('datetime')
def date_format(value):
months = ('Enero','Febrero',"Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre")
month = months[value.month-1]
hora = str(value.hour).zfill(2)
minutos = str(value.minute).zfill(2)
return "{} de {} del {} a las {}:{}hs".format(value.day, month, value.year, hora, minutos)
There is a jinja2 extension you can use just need pip install (https://github.com/hackebrot/jinja2-time)

Is it possible to use the truncate tag in django templates without getting the ...?

if value = "manbearpig" and in templates you called {{value|truncate:6}} you would get a displayed value along the lines of manbe....
How can I get the same result just without the ... in the end?
You can use the slice filter. It works the same as regular slicing built into Python.
{{ value|slice:":6" }}

Django template length filter broken for _set?

I use |length filter in my templates to display the recordcount of my objects, however I'm currently forced to use .count since it seems that using the filter against a related set doesn't work! The following
{{ myobject.retatedObject_set.all|length }}
prints literally:
{{ myobject.retatedObject_set.all|length }}
And this:
{{ myobject.retatedObject_set.all.count }}
returns the expected result...
BUT: count() generates an extra SQL query, which is why I always use |length filter which doesn't! (see my answer: https://stackoverflow.com/a/18578147/267719 to question django - show the length of a queryset in a view)
Can this be considered a bug in the Django template engine? How can I avoid the extra query?
EDIT:
After an hard debug I realized that the problem was the use of the django-debug-toolbar (which prints in its panels each filter used as normal strings) plus the use of AngularJS (which has the same syntax for its templates). I solved by reconfiguring AngularJS to use different symbols:
config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
});

Django separate thousands in template

My model is returning a Decimal(1234567.50), I can't seem to display the Decimal with a thousands separator. Does Django have a way to do this? Do I need to create my own template filter?
Thanks.
You can use the intcomma filter.
Add humanize to the installed apps in settings.py and load it in the template.
{% load humanize %}
{{ my_num|intcomma }}
One easy way is to import locale and do the formatting in your view function.
Even easier to read this: http://docs.djangoproject.com/en/dev/topics/i18n/#overview
For format localization, it’s just
necessary to set USE_L10N = True in
your settings file. If USE_L10N is set
to True, Django will display numbers
and dates in the format of the current
locale. That includes field
representation on templates, and
allowed input formats on the admin.
You could add the following to settings.py:
USE_THOUSAND_SEPARATOR = True
That should work and you don't have to act with loading stuff.
https://docs.djangoproject.com/en/4.1/ref/settings/#use-thousand-separator

Why won't Django auto-escape my <script> tags?

My Django app has a Person table, which contains the following text in a field named details:
<script>alert('Hello');</script>
When I call PersonForm.details in my template, the page renders the script accordingly (a.k.a., an alert with the word "Hello" is displayed). I'm confused by this behavior because I always thought Django 1.0 autoescaped template content by default.
Any idea what may be going on here?
UPDATE: Here's the snippet from my template. Nothing terribly sexy:
{{ person_form.details }}
UPDATE 2: I have tried escape, force-escape, and escapejs. None of these work.
You need to mark the values as | safe I think (I'm guessing that you're filling in the value from the database here(?)):
{{ value|safe }}
Could you post a sample of the template? Might make it easier to see what's wrong
[Edit] ..or are you saying that you want it to escape the values (make them safe)? Have you tried manually escaping the field:
{{ value|escape }}
[Edit2] Maybe escapejs from the Django Project docs is relevent:
escapejs
New in Django 1.0.
Escapes characters for use in JavaScript strings. This does not make the string safe for use in HTML, but does protect you from syntax errors when using templates to generate JavaScript/JSON.
[Edit3] What about force_escape:
{{ value|force_escape }}
...and I know it's an obvious one, but you're absolutely certain you've not got any caching going on in your browser? I've tripped over that one a few times myself ;-)
Found the problem. The JSON string I'm using to render data to some Ext widgets is the culprit. Big thanks to Jon Cage. Answer accepted despite the problem being caused by another source.