I am planning to implement Arabic translation that translates it making a whole sentence to be written right-to-left. How should I do this?:
<!-- parent.html -->
{% blocktrans %}
{% block category %}{% endblock category %} - Site Name
{% endblocktrans %}
<!-- child.html -->
{% extends 'parent.html' %}
{% block category %}Books{% endblock category %}
for Arabic translation I need to use blocktrans, and I need to use different children names as well.
The docs of blocktrans state the following:
Other block tags (for example {% for %} or {% if %}) are not allowed inside a blocktrans tag.
block is another block tag, so it is not supported inside blocktrans either. The only thing allowed inside blocktrans is a direct variable substitution (without any filters, or attribute / method resolution using .).
In other words, what you're asking for is simply not possible with blocktrans. You'll have to reorganize your templates accordingly.
Related
On my wagtail blog, I have a simple model that will be the index page listing different articles, defined in my models.py as:
class ArticleIndex(Page):
description = models.CharField(max_length=255, blank=True,)
content_panels = Page.content_panels + [FieldPanel("description", classname="full")]
I have some template tags setup to show categories and tags in the sidebar, which should only activate on the index page, not actual article pages. I have this setup thusly:
{% if article_index %}
{% categories_list %}
{% tags_list %}
{% endif %}
If I remove the if condition, everything displays as I want, so I know it is not an issue with the template tags.
I don't understand why {% if article_index %} is failing, as that's what the page type is.
How can I print out what the actual page type is to see where the discrepancy is, or to see why the if condition is failing?
{% if article_index %} means "if the variable article_index is defined and has a true value". Since you haven't defined a variable named article_index - and there's nothing in Wagtail that makes a variable of that name appear just because the page type is ArticleIndex - it will always be false.
On the other hand, the variable page is always available, so an alternative way of achieving this would be:
{% if page.content_type.model == 'articleindex' %}
However, since each page type has its own dedicated template, it usually isn't necessary to do this kind of check based on page type. The normal way to have different things showing in the sidebar is to use template inheritance - for example, if your base.html template is:
<html>
<head>...</head>
<body>
<div id="sidebar">
{% block sidebar %}
{% endblock %}
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
then you can set the content of the sidebar just for the article index page by defining {% block sidebar %} in article_index.html:
{% extends "base.html" %}
{% block sidebar %}
{% categories_list %}
{% tags_list %}
{% endblock %}
{% block content %}
main page content goes here
{% endblock %}
I noticed that I started using include template a lot. One of my template files has 20+ include tags.
Some of them are for modal dialogs that in turn have include for different form field sets. I am also using basically the same buttons with different data attributes so these are also done with include tags. Some my "fragments" that I use with include have around only five lines of HTML code.
I worry if this is too much and can negatively affect performance (since Django loads another files, etc..)
For example whis is markup of one of my HTML fragments I am using with include:
<div class="form-group">
<input type="url" class="form-control" id="video-link-input" name="video_link"
placeholder="YouTube link">
</div>
<input type="hidden" id="video_id" name="video_id" value="">
<img class="img-fluid img-thumbnail" id="video-img-preview">
Hope the question is not too broad. I would just like to avoid possible bad practice.
Overly fragmented templates will impact your performance, but not because Django loads files.
With the default settings, Django caches template files when DEBUG=False:
django.template.loaders.cached.Loader
...
This loader is automatically enabled if OPTIONS['loaders'] isn’t
specified and OPTIONS['debug'] is False (the latter option defaults to
the value of DEBUG).
IMHO, having lots of includes is not a bad practice in itself. The alternative would be repeating the code, which violates the DRY principle.
If you find yourself including the same template multiple times within one template, you might want to consider a custom inclusion tag.
If you are really worried about performance, look into caching and specifically template fragment caching.
According to Django documentation:
using {% block %} is faster than using {% include %}
heavily-fragmented templates, assembled from many small pieces, can
affect performance
You can use extends and block
Few examples:
In base.html I use these blocks
...
{% block navbar %}
{% endblock %}
{% block sidebar %}
{% endblock %}
{% block searchbar %}
{% endblock %}
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
...
Now I extend base.html into login.html. Say my login.html just need navbar, content, and footer
{% extends 'base.html' %}
<h1>Login </h1>
{% block navbar %}
This is my navbar
{% endblock %}
{% block content %}
Here is my login form
{% endblock %}
{% block footer %}
This is footer
{% endblock %}
Now I extend base.html into home.html. Say my home.html need navbar, sidebar, searchbar, content, and footer
{% extends 'base.html' %}
<h1>Home page </h1>
{% block navbar %}
This is my navbar
{% endblock %}
{% block sidebar %}
This is sidebar
{% endblock %}
{% block searchbar %}
{% endblock %}
{% block content %}
This is homepage contents. This will not render which you use in login.html **content** block
{% endblock %}
{% block footer %}
{% endblock %}
I want to be able to reuse the same block tag multiple times in derived html.
something like:
base.html
<body>
{% block panel %}
# some basic panel structure inside this block
{% endblock %}
</body>
derived.html
{% extends base.html %}
--first panel
<div class="col">
{% block panel %}
# override things like panel header
{% endblock %}
</div>
--second panel
<div class="col">
{% block panel %}
# again override some panel stuff from base template
{% endblock %}
</div>
Is there anyway i can achieve this in Django?
No, it will result in template syntax error. The best you can do is to include as many block tags as you require in base and reuse them. Or you can even loop the blocks in base.
I haven't tested it out, but theoretically it should work. In your base, create a loop block, in below example it creates 6 blocks, block content1..... content6
{% for i in '123456' %}
{% block content{{i}} %}
Foo
{% endblock content{{i}} %}
{% endfor %}
No, you can not. The best way to do it is, assign each block for each panel or if you have multipanel then run the loop for the block.
In your current case (i assuming two panel in single derived file) it would be like this-
base.html
<body>
{% block content %}
<!-- all your panels -->
{% endblock %}
</body>
derived.html
{% extends "base.html" %}
{% block content %}
<div class="col">
<!-- First panel -->
<!-- Second panel -->
</div>
{% endblock %}
The block is just for reducing the redundant work which unique to each extended file. so you can only referred it to single time in any extended file.
I have a piece of html that I want present in all pages, except one. If not for this page, I would have put it in the base.html and extended.
Is there a way other than putting the code individually in all the required pages?
From template-inheritance docs,
The template engine will notice the {% block %} tags in base.html and replace those blocks with the contents of the child template.
BUT
If the child template didn’t define the block, the value from the
parent template is used instead. Content within a {% block %} tag in a
parent template is always used as a fallback.
So in that case you can use {% block %} tag in the base.html.
{% block content %}
<!-- Your content here-->
{% endblock %}
You don't have to define that block in every template as the parent {% block %} is used as an fallback.
{% extends 'base.html' %}
So in your exceptional case just define that {% block %} tag with no data or something else.
{% extends 'base.html' %}
{% block content %}
<!-- Nothing goes here -->
{% endblock content %}
You can put it into a block that gets overridden with nothing in order to have it ignored. For example:
base.html
{% block content %}
<div>
This should show on all pages except for this one
</div>
{% endblock content %}
included-page.html (The div will be included on this page)
{% extends 'base.html' %}
ignored-page.html (The div will be ignored on this page)
{% extends 'base.html' %}
{% block content %}
{% endblock content %}
I'm using django-pagination to paginate my pages. It works great, but I would like to set up
<link rel="prev" href="http://www.example.com/foo/?page=1" />
<link rel="next" href="http://www.example.com/foo/?page=3" />
to the <head>, like it is recommended by google .
However I found no way ho to do this (without extra queries at least). First I tried to edit the pagination/templates/pagination.html with something like this
{% block extra_head %}
<link rel=... ... />
{% endblock %}
Which of course did not work (pagination.html is included by the {% paginate %} tag, it does not extend my layout.html). Next, I tried to modify my template for /foo/ view to something like this (adding the {% block extra_head %}):
{# foo.html #}
{% extends "layout.html" %}
{% block content %}
{% load pagination_tags %}
{% autopaginate object_list %}
{% paginate %}
{% for obj in object_list %}
{{ obj }}
{% endfor %}
{% paginate %}
{% endblock %}
{% block extra_head %}
<link rel="prev" href="?page={{ page_obj.previous_page_number }}"/>
{% endblock %}
But this won't work either, as the page_obj variable is only available in scope of {% block content %}. A could call
{% autopaginate object_list %}
in the extra_head block, but that will mean an extra hit to the db (and possibly other side effects that I'm not aware of). Is there an elegant way to solve this, ideally as DRY as possible?
Edit: I'm using django 1.2.
You can do {% autopaginate %} in higher-level block, then paginated objects will be available in sub-blocks. If you don't have higher level block it is possible to do this in base template:
{% block root %}
...
{% endblock %}
And in extended template:
{% extends "base.html" %}
{% load pagination_tags %}
{% block root %}
{% autopaginate objects 10 %}
{{ block.super }}
{% endblock %}
<!-- the rest of your code -->
Now, to get a different rendering of paginator in head, you can make use of the with tag:
{% with we_are_in_head=1 %}
{% paginate %}
{% endwith %}
And override templates/pagination/pagination.html with something like this:
{% if we_are_in_head %}
# Your links to next and prev only
{% else %}
# original code
{% endif %}
A moral
This is not elegant and the reason is that pagination should be implemented in the view. Templates are for rendering only, template-tags too. Pagination makes extra sql queries, it also parses arguments from request, template is totally wrong place for this code, so workarounds has to be invented. These workarounds might break on next release of django, they are also subtle and can be accidentally broken by other developer.
We can call autopaginate in a view and then use {% paginate %} as usual. Here is a recipe if somebody still face the described problem:
from pagination.templatetags.pagination_tags import AutoPaginateNode
def autopaginate(request, context, queryset_var, paginate_by):
""" It allows us to use paginated objects in different template blocks """
autopagination = AutoPaginateNode(queryset_var, paginate_by)
# Inject a request - it's required by `autopagination` function
context['request'] = request
autopagination.render(context)