I have the following in a template -
<tes:productiondate>{% now "Y-m-d" %}T{% now "H:i:s" %}-{{{% now "u" %}|truncatechars:4}}</tes:productiondate>
It's giving me an error
Could not parse some characters: |{% now "u" %}||truncatechars:4
{% now "u" %} does display correctly the problem is that by default it displays 6 characters and I only want it to display 4 characters.
I'm realizing that truncatechars it's the right way to do it because I don't want the "..." so how do I go about shortening the string of 6 characters to be only 4?
You can't apply a filter to template tag's output. In trunk version of django {% now %} tag can save formatted time to variable:
{% now "u" as msec %}{{ msec|truncatechars:4 }}
But in the current stable django (1.7.2) the as keyword is not supported.
So you have to write custom template tag. It is easy:
import datetime
from django import template
register = template.Library()
#register.simple_tag
def microseconds(format_string):
return datetime.datetime.now().strftime('%f')[:4]
Related
My head could not click how to translate numbers in django translation. It is not possible to translate by string id. I could print 2020 like:
{% translate '2' %}{% translate '0' %}{% translate '2' %}{% translate '0' %}
Obvioulsy, It is not the way. So, I am missing something. I would want something like:
{% translate "2020"|number %} # May be ?? It should be that easy right?
It should be that, translation from 0 to 9.
Django doesn't have this functionality (yet), but you can achieve the same by creating a custom template tag. You can read the whole documentation of creating the tag here, Custom template tags and filters.
By this way, you can translate Arabic Numerals (or anything) to any form, all you need is a mapper dict and a function that converts things by using the mapper dict.
We need to have a dict that has the source numerals as keys and target numeral as values. In this case, I assume you need to translate from Arabic numerals to nepali numerals
So, I have created a simple mapper using dict and converted the receiving value to something else using the translate_nepal_numeral(...) function.
from django import template
from django.template.defaultfilters import stringfilter
NUMBER_MAP = {
"0": "०",
"1": "१",
"2": "२",
# and so on
}
register = template.Library()
#register.filter()
#stringfilter
def translate_nepal_numeral(value):
try:
return "".join([NUMBER_MAP[char] for char in value])
except KeyError:
return value
Then in your template,
{% load custom_numerals %}
{{ "2010"|translate_nepal_numeral }}
Examples
In [3]: translate_nepal_numeral("2020")
Out[3]: '२०२०'
In [4]: translate_nepal_numeral("2120")
Out[4]: '२१२०'
In [5]: translate_nepal_numeral("2120a")
Out[5]: '2120a'
Notes
If you are passing a non-numeral, this function will return the input
Looks like a question that should be already covered, but after spending some time, I did not find how to check that a variable is numeric in Django template.
Something like
{% if my_var.isnumeric %}
# do something
{% endif %}
UPDATE
As I learnt from the below discussion, there seems to be no built-in tag to check this, and we end up having to create our own template tag.
Assuming that "numeric" means "contains only digits" (and no decimal point, no minus sign, etc.)
Custom filter is your best bet:
from django import template
register = template.Library()
#register.filter(is_safe=True)
def is_numberic(value):
return "{}".format(value).isdigit()
Docs about custom template filters: https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/
Usage in templates:
{% load your_custom_lib %}
...
{% if something|is_numberic %}...
If you consider integers as numeric (positive and negative), then the function becomes:
try:
int("{}".format(value))
except ValueError:
return False
else:
return True
In case "numeric" means "integer or float", then use float instead of int. But note that this will also recognize -12E3 as numeric, because:
>>> -12E3
-12000.0
Does this work ?
{{ value|divisibleby:"1" }}
EDIT: Nope, raises an exception if a string is given.
I want to use AngularJS with Django however they both use {{ }} as their template tags. Is there an easy way to change one of the two to use some other custom templating tag?
For Angular 1.0 you should use the $interpolateProvider apis to configure the interpolation symbols: http://docs.angularjs.org/api/ng.$interpolateProvider.
Something like this should do the trick:
myModule.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
Keep in mind two things:
mixing server-side and client-side templates is rarely a good idea and should be used with caution. The main issues are: maintainability (hard to read) and security (double interpolation could expose a new security vector - e.g. while escaping of serverside and clientside templating by themselves might be secure, their combination might not be).
if you start using third-party directives (components) that use {{ }} in their templates then your configuration will break them. (fix pending)
While there is nothing we can do about the first issue, except for warning people, we do need to address the second issue.
you can maybe try verbatim Django template tag
and use it like this :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
{% verbatim %}
<div ng-app="">
<p>10 is {{ 5 + 5 }}</p>
</div>
{% endverbatim %}
If you did separate sections of page properly then you can easily use angularjs tags in "raw" tag scope.
In jinja2
{% raw %}
// here you can write angularjs template tags.
{% endraw %}
In Django template (above 1.5)
{% verbatim %}
// here you can write angularjs template tags.
{% endverbatim %}
We created a very simple filter in Django 'ng' that makes it easy to mix the two:
foo.html:
...
<div>
{{ django_context_var }}
{{ 'angularScopeVar' | ng }}
{{ 'angularScopeFunction()' | ng }}
</div>
...
The ng filter looks like this:
from django import template
from django.utils import safestring
register = template.Library()
#register.filter(name='ng')
def Angularify(value):
return safestring.mark_safe('{{%s}}' % value)
So I got some great help in the Angular IRC channel today. It turns out you can change Angular's template tags very easily. The necessary snippets below should be included after your angular include (the given example appears on their mailing lists and would use (()) as the new template tags, substitute for your own):
angular.markup('(())', function(text, textNode, parentElement){
if (parentElement[0].nodeName.toLowerCase() == 'script') return;
text = text.replace(/\(\(/g,'{{').replace(/\)\)/g, '}}');
textNode.text(text);
return angular.markup('{{}}').call(this, text, textNode, parentElement);
});
angular.attrMarkup('(())', function(value, name, element){
value = value.replace(/\(\(/g,'{{').replace(/\)\)/, '}}');
element[0].setAttribute(name, value);
return angular.attrMarkup('{{}}').call(this, value, name, element);
});
Also, I was pointed to an upcoming enhancement that will expose startSymbol and endSymbol properties that can be set to whatever tags you desire.
I vote against using double parentheses (()) as template tag. It may work well as long as no function call is involved but when tried the following
ng:disabled=(($invalidWidgets.visible()))
with Firefox (10.0.2) on Mac I got a terribly long error instead of the intended logic. <[]> went well for me, at least up until now.
Edit 2012-03-29:
Please note that $invalidWidgets is deprecated. However I'd still use another wrapper than double braces. For any angular version higher than 0.10.7 (I guess) you could change the wrapper a lot easier in your app / module definition:
angular.module('YourAppName', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<[');
$interpolateProvider.endSymbol(']>');
});
API docs.
You could always use ng-bind instead of {{ }}
http://docs.angularjs.org/api/ng/directive/ngBind
<span ng-bind="name"></span>
I found the code below helpful. I found the code here: http://djangosnippets.org/snippets/2787/
"""
filename: angularjs.py
Usage:
{% ng Some.angular.scope.content %}
e.g.
{% load angularjs %}
<div ng-init="yourName = 'foobar'">
<p>{% ng yourName %}</p>
</div>
"""
from django import template
register = template.Library()
class AngularJS(template.Node):
def __init__(self, bits):
self.ng = bits
def render(self, ctx):
return "{{%s}}" % " ".join(self.ng[1:])
def do_angular(parser, token):
bits = token.split_contents()
return AngularJS(bits)
register.tag('ng', do_angular)
If you use django 1.5 and newer use:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
If you are stuck with django 1.2 on appengine extend the django syntax with the verbatim template command like this ...
from django import template
register = template.Library()
class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
def render(self, context):
return self.text
#register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
In your file use:
from google.appengine.ext.webapp import template
template.register_template_library('utilities.verbatim_template_tag')
Source:
http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html
You can tell Django to output {{ and }}, as well as other reserved template strings by using the {% templatetag %} tag.
For instance, using {% templatetag openvariable %} would output {{.
I would stick with a solution that uses both django tags {{}} as well angularjs {{}} with a either a verbatim section or templatetag.
That is simply because you can change the way angularjs works (as mentioned) via the $interpolateProvider.startSymbol $interpolateProvider.endSymbol but if you start to use other angularjs components like the ui-bootstrap you will find that some of the templates are ALREADY built with standard angularjs tags {{ }}.
For example look at https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.
If you do any server-side interpolation, the only correct way to do this is with <>
$interpolateProvider.startSymbol('<{').endSymbol('}>');
Anything else is an XSS vector.
This is because any Angular delimiters which are not escaped by Django can be entered by the user into the interpolated string; if someone sets their username as "{{evil_code}}", Angular will happily run it. If you use a character than Django escapes, however, this won't happen.
I am pulling a name from a database which is stored as myname. How do I display this inside a Django template as Myname, with the first letter being in uppercase.
Using Django built-in template filter called title
{{ "myname"|title }}
I know it's a bit late, but you can use capfirst:
{{ "waiting for action"|capfirst }}
This will result into "Waiting for action"
This solution also works if you have multiple words (for example all caps):
{{ "ALL CAPS SENTENCE"|lower|capfirst }}
This will output "All caps sentence".
The title filter works fine, but if you have a many-words string like: "some random text", the result is going to be "Some Random Text". If what you really want is to uppercase only the first letter of the whole string, you should create your own custom filter.
You could create a filter like this (follow the instructions on how to create a custom template filter from this doc - it's quite simple):
# yourapp/templatetags/my_filters.py
from django import template
register = template.Library()
#register.filter()
def upfirstletter(value):
first = value[0] if len(value) > 0 else ''
remaining = value[1:] if len(value) > 1 else ''
return first.upper() + remaining
Then, you should load the my_filters file at your template, and use the filter defined there:
{% load my_filters %}
...
{{ myname|upfirstletter }}
It worked for me in template variable.
{{ user.username|title }}
If the user is "al hasib" then the it will return "Al Hasib"
or
{{ user.username|capfirst }}
If user is 'hasib' then the last one will return "Hasib"
Both look something like same but there's some differences.
use
{{"myname"|title}}
this will make the fist letter of each word capital
Just use {{myname | capfirst}}
In Django the template filter capfirst capatialize the first letter of a given string.
Django has truncatewords template tag, which cuts the text at the given word count. But there is nothing like truncatechars.
What's the best way to cut the text in the template at given char-length limit?
This has recently been added in Django 1.4. e.g.:
{{ value|truncatechars:9 }}
See doc here
{{ value|slice:"5" }}{% if value|length > 5 %}...{% endif %}
Update
Since version 1.4, Django have a built-in template tag for this:
{{ value|truncatechars:9 }}
I made my own template filter, that add "..." to the end of (last word of) the (truncated) string as well:
from django import template
register = template.Library()
#register.filter("truncate_chars")
def truncate_chars(value, max_length):
if len(value) > max_length:
truncd_val = value[:max_length]
if not len(value) == max_length+1 and value[max_length+1] != " ":
truncd_val = truncd_val[:truncd_val.rfind(" ")]
return truncd_val + "..."
return value
If you go on creating your own custom template tag, consider to leverage the native Django util Truncator.
The following is a sample usage of the Truncator util:
>>> from django.utils.text import Truncator
>>> Truncator("Django template tag to truncate text")
<Truncator: <function <lambda> at 0x10ff81b18>>
>>>Truncator("Django template tag to truncate text").words(3)
u'Django template tag...'
Truncator("Django template tag to truncate text").chars(20)
u'Django template t...'
And here how you can use it inside a Django template tag:
from django import template
from django.utils.text import Truncator
register = template.Library()
#register.filter("custom_truncator")
def custom_truncator(value, max_len, trunc_words=False):
""" Set trunc_words=True to truncate by words instead of by chars."""
truncator = Truncator(value)
return truncator.words(max_len) if trunc_words else truncator.chars(max_len)
Eventually you can import the custom_truncator in any Django template.
Here it is in the Django Documentation, Built-in template tags and filters: truncatechars
You should write a custom template filter: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters
Have a look at how truncatewords is built in django.utils.text
You can achieve your goal with similar code:
{{ value_of_text|truncatechars:NUM_OF_CHARS_TO_TRUNCATE}}
where NUM_OF_CHARS_TO_TRUNCATE is number of chars to leave.
slice
Adding a "truncate" filter was a feature request for 4 years but finally landed in trunk, as far as I understand https://code.djangoproject.com/ticket/5025 - so we’ve to wait for the next release or use trunk.