I wrote a template tag for Django, that is used like, say, {% foo bar="foobar"%}. The tag takes the bar argument value, uses ugettext on it and renders the tag with translated string.
So, basically, the tag's implementation looks more or less like this:
#register.simple_tag
def foo(bar):
return "something something " + ugettext(bar)
Unfortunately, we are using ugettext with a variable, and that means that Django won't mark our bar argument's value for translation.
I was looking for a solution in Django makemessages as well as {% trans %} code, but didn't find anything that would clearly say how the "marking for translation" thing is done there. So, my question is: how to do it? How to force Django to think that my tag's bar argument value is supposed to be translated, so it appears in .po(t) file after executing manage.py makemessages?
Instead of creating "custom" trans tag, one can pass the string using _() syntax, so the argument gets an already translated string.
In case of the tag from question - that means that we can change the tag implementation to simple:
#register.simple_tag
def foo(bar):
return "something something " + bar
But one does not have to use something like this:
{% trans "foobar" as var %}
{% foo bar=var %}
And instead:
{% foo bar=_("foobar") %}
Which is convenient enough, does not waste lines and variables, and marks the string for translation.
See: https://docs.djangoproject.com/en/1.8/topics/i18n/translation/#string-literals-passed-to-tags-and-filters
Related
I've got modules that if enabled/disabled would require a different arrangement of tables and iframes on the frontend webpage. In order to do this I set up a function to check which modules are enabled/disabled and assigned a number to each 'set' and will be created separate templates for each "set1.html", "set2.html", "set3.html", etc...
I'd like to utilize one single view where I can pass the set number from from function I created but I can't seem to figure out how.
def homeset(request):
return render(request, 'app/set1.html', {})
Looking to figure out some way to make the "1" the return of the function I created to determine which set# to load as template and would prefer to not have to create a view for every single template needed.
Just taking a stab at this, do you have a problem with setting the template name before rendering?
def homeset(request):
# define 'my_set'
# define num
...
my_template_name = None
if num in my_set:
my_template_name = 'app/set{}.html'.format(num)
return render(request, my_template_name)
Looks like Scott Skiles answered your question, but an alternative way is to use a single base template and the "include" templatetag.
You can pass the set number to the template and use the "if" templatetag" to include the content from appropriate template(s) for each set number.
{% if set_num == 1 %}
{% include "foo/bar.html" %}
{% elif set_num == 2 %}
{% include "foo/two.html" %}
{% endif %}
How can I call a method, pass multiple parameters to it and render the result in a html template? I can't find a simple solution which works in all circumstantials. I'm aware about #register.filter and #register.simple_tag but there's alway an error being thrown. If it's not thing, it's another. For example, simple_tag works when I render it, but throws an error when I call if.
So how can I call a method from an html template in the following ways:
{{method1(a, b)}}
{% if method1(a, b) == some_value %} {{method1(a, b)}} {%endif%}
Note I don't need advice like "you're doing something wrong, you should change your architecture" because that's not the case here. I just a simple way to do what I want. In Rails, for example, I can do it very, very easily.
You can use an assignment tag to assign the value received from the template tag into a variable which then can be used anywhere in the template.
#register.assignment_tag
def method1(a,b):
...
Then in your template you can call this template tag and assign its value to a variable method_value.
{% method1 a b as method_value %}
Then use this variable in the template.
{{method_value}}
{% if method_value == some_value %} {{method_value}} {%endif%}
In a Django template how do I remove the first Zero from all the this mobile numbers I'm displaying. In Python I have tried this but with no success....
{% for object in data %}
{{ object.mobile.lstrip('0') }}
{% endfor %}
views.py
def sms(request, incentive):
objectQuerySet = Recipient.objects.filter(incentiveid=incentive)
context = {'data':objectQuerySet}
return render_to_response('smssend.html', context, context_instance=RequestContext(request))
There are many ways to do that.
write custom template filter
filter user input and store phones with leading zeros already stripped
create a custom object #property returning mobile with zeroes stripped (this one a little bit dirty)
do cleanup before rendering template
I assume you will need to use similar logic in other locations of your application so why not just add a method to your model to clean the data? The code below assumes your mobile field is a string.
class Recipient(models.Model):
...
def mobile_no_zero(self):
return self.mobile[1:] if self.mobile.startswith('0') else self.mobile
And then you can call the method from your template:
{% for object in data %}
{{ object.mobile_no_zero }}
{% endfor %}
You should pass your data to your template in the correct format. Django templates are not "Python interspersed with HTML" like PHP is.
For example, when you first pass your data in your view, you should make sure that it is an iterable with the zeroes already stripped.
There is no lstrip in the Django template mini-language.
Edit: If you know that the first digit will always be a 0, you can also do this:
{{ object|slice:"1:" }}
There is one method that does work (but is more of a kludge that anything and removes 0 or more 0s) - and only if the number can be converted to a float to start with (ie, no spaces)
In [23]: t = Template('{{ value|floatformat:0 }}')
In [24]: t.render(Context({'value': '00123'}))
Out[24]: u'123'
You can use cut ( it will cut all zeros from number )
or you can use
phone2numeric
Imo its beter opption
If I have a template variable called num_countries, to pluralize with Django I could just write something like this:
countr{{ num_countries|pluralize:"y,ies" }}
Is there a way to do something like this with jinja2? (I do know this doesn't work in jinja2) What's the jinja2 alternative to this?
Thanks for any tip!
Guy Adini's reply is definitely the way to go, though I think (or maybe I misused it) it is not exactly the same as pluralize filter in Django.
Hence this was my implementation (using decorator to register)
#app.template_filter('pluralize')
def pluralize(number, singular = '', plural = 's'):
if number == 1:
return singular
else:
return plural
This way, it is used exactly the same way (well, with parameters being passed in a slightly different way):
countr{{ num_countries|pluralize:("y","ies") }}
Current Jinja versions have the i18n extension which adds decent translation and pluralization tags:
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}
You can use this even if you don't actually have multiple language versions - and if you ever add other languages you'll have a decent base which requires no changes (not all languages pluralize by adding an 's' and some even have multiple plural forms).
According to Jinja's documentation, there is no built in filter which does what you want. You can easily design a custom filter to do that, however:
def my_plural(str, end_ptr = None, rep_ptr = ""):
if end_ptr and str.endswith(end_ptr):
return str[:-1*len(end_ptr)]+rep_ptr
else:
return str+'s'
and then register it in your environment:
environment.filters['myplural'] = my_plural
You can now use my_plural as a Jinja template.
You also want to check if the word is already plural. Here is my solution:
def pluralize(text):
if text[-1:] !='s':
return text+'s'
else:
return text
Then register the tag to your environment (this can be applied to the Django templating engine too).
I have a few values that I would like to pass into a filter and get a URL out of it.
In my template I have:
{% if names %}
{% for name in names %}
<a href='{{name|slugify|add_args:"custid=name.id, sortid=2"}}'>{{name}}</a>
{%if not forloop.last %} | {% endif %}
{% endfor %}
{% endif %}
In my templatetags I have:
#register.filter
def add_args(value, args):
argz = value.strip() + '-' + 'ARGS'
arglist = args.split(',')
for arg in arglist:
keyval = arg.split('=')
argz.join(keyval[0] + 'ZZ' + keyval[1])
argz.join('QQ')
return argz
The output URL should look like:
http://foo.org/john-smith-ARGScustidZZ11QQsortidZZ2
Where ARGS is the start of the arguments, ZZ is '=' and QQ is an '&' equivalent.
First of all: This would work, but I get the custid=name.id coming in the add_args(), where I want to have custid=11 to come in. How pass in the id as an id and not text.
Also, is there a way to just send in an array of key=>value like in PHP.
In PHP I would build an array, let say:
arglist = array('custid' => $nameid, 'sortid' => $sortid );
Then I would pass the arglist as an argument to add_args() and in add_args() I would do
foreach( arglist as $key => $value)
$argstr .= $key . 'ZZ' . $value . 'QQ'.
Does anyone have a better way of making this work?
Note: if I have to pass all arguments as a string and split them up in the filter I don't mind. I just don't know how to pass the name.id as its value ...
This "smart" stuff logic should not be in the template.
Build your end-of-urls in your view and then pass them to template:
def the_view(request):
url_stuff = "custid=%s, sortid, ...." % (name.id, 2 ...)
return render_to_response('template.html',
{'url_stuff':url_stuff,},
context_instance = RequestContext(request))
In template.html:
....
<a href='{{url_stuff}}'>{{name}}</a>
....
If you need a url for a whole bunch of objects consider using get_absolute_url on the model.
You can't pass name.id to your filter. Filter arguments can be asingle value or a single literal. Python/Django doesn't attempt any "smart" variable replacement like PHP.
I suggest you to create a tag for this task:
<a href='{% add_args "custid" name.id "sortid" "2" %}{{name|slugify}}{% end_add_args %}'>{{name}}</a>
This way you can know which argument is a literal value and which should be taken fron context etc... Docs are quite clear about this, take a look at the example.
Also if this name is any way related to a model, say we want to get to the permalink, adding a method that returns the URL with the proper arguments might be the tidiest solution.
Overall, I would refrain putting too much logic into templates. Django is not PHP.
You're calling argz.join a couple times and never assigning the results to anything: maybe you're operating under the misconception that the join method of a string has some mysterious side effect, but it doesn't -- it just returns a new string, and if you don't do anything with that new string, poof, it's gone. Is that at least part of your problem...?