Django template: Translate include with variable - python

I have a template in which you can pass a text variable. I want to include this template into another one but with a translated text as it's variable. How can you achieve this?
I would like something like this:
{% include "a_dir/stuff.html" with text={% trans "Load more promotions" %} %}
I tough about writing my own template tag that will perform a ugettext but then when creating the .po file, the text variable will not be taken automatically.
I don't want to do this work in the view since all our translations take place in the templates.

You can put the translated string into a variable with the as syntax. For instance:
{% trans "Load more promotions" as promotions %}
{% include "a_dir/stuff.html" with text=promotions %}
See the docs for more details.

A shorter way is
{% include 'a_dir/stuff.html' with text=_("Load more promotions") %}
which also works fine with variables

Related

Highlighting the inner code blocks in Django Template Engine with django-pygmentify

I'm using django-pygmentify package in order to highlight my code blocks in my Django templates. The thing is that this package only supports code blocks as input. I have a model field that keeps markdown data. This markdown content might contain code blocks. (using ``` symbol)
Now, how can I highlight its inner code blocks??
Imagine I have a field that only contains source code. Like:
print('Hey..!')
In that case, this one works properly.
{% load pygmentify_tags %}
...
{% pygmentify %}
{{post.code}}
{% endpygmentify %}
Imagine my field contains the following content.
## Hello
This is my first step working with Python.
```python
print('Hey..!')
‍```
In this case, how can I implement it?? I can render that whole markdown content with {{post.body|markdown|safe}}, but how can I highlight those code blocks?? I also want to give all those code blocks a class name .code-block for better styling. Should I create a custom template tag?
You may use html standard <code> tag like this:
{% load pygmentify_tags %}
...
{% pygmentify %}
<code>
{{post.code}}
</code>
{% endpygmentify %}
This will separate the code section and at the same time will apply pygmentify to it.

Is this okay to add slashes in below code at template of Django?

I am trying to solve a problem. During the process I got this question.
{% if request.path == '/{{sub_cat.sub_cat_parent.cat_slug}}/{{sub_cat.sub_cat_slug}}/' %}
<div class="alert-secondary">Active</div>
{% else %}
How do I properly include slashes in here '/{{sub_cat.sub_cat_parent.cat_slug}}/{{sub_cat.sub_cat_slug}}/'? Is it okay to use {{ within {% template tags? what am I doing wrong in here?
"variable substitution" ({{ somevar }}) syntax is indeed not supported in templatetags arguments - which makes sense if you consider that in the context of template rendering, this syntax would be the equivalent of a "print" statement.
This doesn't mean you can't pass context variables to templatetags - else templatetags would be of very limited use - but you do so by just mentionning them ie assuming you have a context variable named "path", you could use it here as
{% if request.path==path %}
...
You can also use filter expressions here, ie this is valid too:
{% if request.path==path|lower %}
(assuming the templatetag's author correctly handled the tags arguments - I let you refer to the documentation for more on this).
Now wrt/ your problem here, you could of course use a custom filter to join the different parts but that would actually be a very bad idea. Django's url handing is based on the idea that you should actually never hardcode an url anywhere - you define and name urls in your urls.py files, and then use the builtin functions (django.core.urlresolvers.reverse()) / templatetags ({% url %}) to generate them.
Here, the proper solution would be to define a get_absolute_url() method on your sub_cat object that returns the correct url (actually the path portion of it) for this object, and test against it in the template.
As far as I'm concerned, I'd even use a second indirection level as a template filter so 1/ your model (or whatever sub_cat is) knows it's own url, and 2/ the template filter can tell if a given sub_cat is "active" for the current request.path so if the spec defining when a sub_cat is "active" is to change you'll only have the template filter function to change instead of having to browse thru all your templates (possibly missing something on the way).
use with clause
{% with "/"|add:sub_cat.sub_cat_parent.cat_slug|add:"/"|add:sub_cat.sub_cat_slug|add:"/" as url_path %}
{% if request.path == url_path %}
<div class="alert-secondary">Active</div>
{% else %}
{% endwith %}
this will work

Break long {% with %} assignment into multiple lines in a Django template [duplicate]

I am creating a custom django template tag by using such a code :
#register.simple_tag(takes_context=True)
def render_listing(context, *args, **kwargs):
... my code ...
This works well, but in my template, it seems that all parameters must be on a single line, for example :
this works:
{% render_listing param1=val1 param2=val2 ... paramN=valN %}
but on multiple lines, it does not work :
{% render_listing param1=val1
param2=val2
...
paramN=valN %}
I tried multiple escape sequences but I did not succeeded,
Is there a way to specify a template tag on multiple lines ?
No, the Django template language does not support multiple line tags. See ticket 8652, which was closed as WONTFIX, or this thread from the django-developers mailing list.
Sometimes, if there is a repeated prefix, you can make it more readable by using the with tag. For example if you have,
{% render_listing param1=long.common.prefix.val1 param2=long.common.prefix.val2 param2=long.common.prefix.val3 %}
you could rewrite as
{% with prefix=long.common.prefix %}
{% render_listing param1=prefix.val1 param2=prefix.val2 param2=prefix.val3 %}
{% endwith %}
Often (but not always), a really long tag is an indication that you're putting too much logic in the template. See if you can move some of it into the view, model method, template tag or template filter.
It's pretty straightforward to enable, though hackish:
import re
from django.template import base
base.tag_re = re.compile(base.tag_re.pattern, re.DOTALL)
"Using" it is simple; one place I find it especially useful is {% include %} tags:
{% include 'my/sweet/modal-template.template' with
message="Hey, do you really want to frob the widget?"
yes="Heck yes I do!"
no="No frickin' way!"
icon="error"
%}
I haven't tested this in more recent versions of Django but I imagine it could be adapted; that worked at least back around 1.8. I should point out that in theory some tags that do custom parsing of their arguments could break; in practice I haven't had any trouble in the last ~10 years of Django programming.

Variable context between two blocks in Django templates?

I have two blocks that call the same method with same variables. I want to call the method only once, but the result is then outsite the scope of the block tags. I've tried calling this method in the parent template header.html and with a with tag, but nothing seems to work.
This is the layout:
{% extends "header.html" %}
{% load navigation_tags %}
{% block header %}
{% get_section site=site as section %}
{% include "foobar.html" with section=section %}
{% endblock header %}
{% block navigation %}
<nav>
<div class="container">
{% get_section site=site as section %}
{% navigation section.slug %}
</div>
</nav>
{% endblock navigation %}
navigation_tags.py
#register.assignment_tag
def get_parent_section(site):
if site.id == settings.FOOBAR_SITE_ID:
section = Section.objects.get(id=settings.FOOBAR_SECTION_ID)
else:
# This is also a section instance.
return site.default_section
As mentioned by 2pacho in another answer and Fernando Cezar in a comment, the easiest way to share values between different sections is to set it in the template context. If you are using the render shortcut function, you can pass a dict as the context parameter to add a value to the rendering context of the template. That would be a good place to add it and this would be the easiest place to put it.
return render(request, 'template.html', {'section': get_parent_section(site)})
However, if for some reason, you can't include it in the context, you can use a decorator to add memoization to your function, so that it will cache the computation results and return it immediately when called with the same parameters. You can use functools.lru_cache to do so, or it's Django backport at django.utils.lru_cache.lru_cache if you are using Python 2.x.
#register.assignment_tag
#functools.lru_cache()
def get_parent_section(site):
if site.id == settings.FOOBAR_SITE_ID:
section = Section.objects.get(id=settings.FOOBAR_SECTION_ID)
else:
# This is also a section instance.
return site.default_section
I wouldn't call a method outside .py . Think that this is using Jinja2 templates,
it's powerful but not in the way that the backend can be.
What I recommend you doing in this case is to generate a context for the template and use this variables there.
Would be as simple as adding it to your context where it's being generated.
context['site_parent'] = get_parent_section(site)
Think that Jinja2 (html) has to be as simple as possible and that can help you with basic coding and time saving (like loops to print the exact same information or show and hide code depending on the context) but I would keep it as simple you can when rendering.
If you would like you can read official django website about templates https://docs.djangoproject.com/en/2.0/topics/templates/
But from my expirience I would keep the method calls in the views.py

Including Blocks from Jinja templates

I would like to include blocks from templates instead of macros, as many templates will be including content from many other templates, so extends isn't an option.
I've read many answers about this, including blocks in included files, but the use case always seems to be different. I suspect this cannot be done.
template1.html
{% block description %}
<p> Here is a description </p>
{% endblock %}
And in template2.html
{% from 'template1.html' import description %} <- doesnt work
You have two options here.
Use a macro, which sounds like something you don't want to do.
Use a template_filter.
Assuming you're using Flask, this is as easy as:
#app.template_filter('get_block')
def template_filter(block, file):
html = render_template(file)
# Then use regex or something to parse
# or even simple splits (better with named blocks), like...
content = html.split('{%% block %s %%}'%(block))[-1]
content = content.split('{%% endblock %%}')[0]
return content
And to use it:
{% 'description'|get_block('template1.html') %}

Categories