Is there a Django equivalent to Mako's callable blocks?
In Mako, if I have a particular bit of HTML that I would like to reuse, I can put it in a "callable block" which can be called from multiple places in the template.
<%def name="makerow(row)">
<tr>
% for name in row:
<td>${name}</td>\
% endfor
</tr>
</%def>
Does Django have something similar to this?
In Django you can include other HTML templates to accomplish this:
{% include "main/includes/subtemplate.html" %}
You can access the same variables in the included template as in the parent template from which it is included. This allows you to reuse HTML in multiple places in a template.
An alternative is to create a custom template tag: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/ This allows you to create your own tags that generate HTML output. The Django documentation provides various examples on how to do this.
Related
I'm receiving this error each time I try to access a list within a Django template. I have checked the answers to similar questions, but the problem is usually a lack of % or some other character somewhere. As long as I can see, this is not the case:
Here I'm passing a dict containing a a list of item id as keys and list of URLs to images as a value for each id. I know I should integrate this into the item model, but since I'm still at development with SQLite3 I cannot store lists easily. And anyway I am intrigued by this problem. So:
<a href="{% url 'details_view' item_id=item.id %}"><img class="hover-image" src="{{ img_gallery[item.id][0] }}" alt="">
Exception Value:
Could not parse the remainder: '['item.id'][0]' from 'img_gallery['item.id'][0]'
Also, yesterday I tried using bootstrap4 flex-grid to easily achieve 5 columns. Since I'm using pagination to retrieve 20 items, my idea was slicing the list of items (model) for each row, like:
{% for item in items[0:5] %}
And I also received the same error, even when this was the recommended aproach in related answers aboput slicing data passed with a view.
In both cases I cannot find the problem, and I think both are somehow related.
I'm using latest Django 1.11.6 with Python 3.5.2.
You seem to be confused between Jinja2 syntax and the Django template syntax. Jinja2 is a separate project, inspired by Django, but not used by Django itself.
In the Django template syntax, variables in {{...}} always use dot notation, [...] subscriptions are not supported. Out of the box, the language does not support dictionary key lookups.
You can write a custom filter to achieve this, like the following, written by culebrón:
from django.template.defaulttags import register
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
then in the template:
{{ img_gallery|get_item:item.id|first }}
Alternatively, you could switch to using Jinja2 in your Django project, replacing the built-in template language: How to use jinja2 as a templating engine in Django 1.8
I'm developing a web application with Django and we have met a dilemma about the design.
We were making one template for every screen, but right now we have detected that some parts of of the screen with the information are repeated all over the different screens. For example, when coming to show personal data of a person, you can show also another data concerning that person, but not personal data (financial data, for instance).
My intuition told me that we should look for a solution in which we could make small templates that we could compose, combine and concatenate and that we should also make different views or functions which would return its own associated template each one.
Thus, person_data() would return the rendered template showing the name, surname, address, etc... and financial_data() would return the rendered template showing the salary, bank account, etc... After that, the desirable thing would be concatenating both or inserting them in a wider template for showing all this together.
<html>
...
{# Html code here #}
...
{# person_data template #}
...
...
{# financial_data template #}
...
{# Html code here #}
...
</html>
So as always I made some research on the net and I found:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
a link which describes how to use include for inserting a template file in another template:
{% include "foo/bar.html" %}
And you can also use a variable from the python function with the path name or an object with render method:
{% include template_name %}
So we could use all this in this way for combining, concatenating, composing and operating on templates. We could choose the one which includes the others and passing it the context for all templates (I suppose, I didn't test anything). But I don't know if I'm well directed or if this is the best way to go. I would appreciate some advice.
I also found another interesting thread in stackoverflow talking about this:
How do you insert a template into another template?
My idea is to have small templates which are used repeatedly in different spots of the web and composing them in Unix-like style, so I would have small visual pieces that would be used once and again saving a lot of hours of writing of code.
Please some advice.
Thanks in advance
Yes, that is a correct approach. I think the best solution is to combine {% include %} and {% extend %}, which will allow you to inherit from a base template (via extend), and include parts you want from other templates (via include).
You'd end up having a base template, a template for the header, the footer, parts of the body etc.
You might also want to read more about it here and here
I have a block of XML that is returned from an API call.
It contains lots of results - person elements like below.
<root><person><name>mark</name><age>18</age></person><person><name>alan</name><age>10</age></person></root>
I want to pass this data structure (or some iterable version if it) to a django template to iterate over.
In my template I want to say
{% for r in results %}
{{ r.name }}
{{ r.age }}
{% endfor %}
I thought this would have been straight forward but its posing problems.
Django templates cannot handle it out-of-the-box. And it doesn't actually sound correct - to pass an XML structure into HTML template to process.
Making custom template tags or filters that would help to iterate over the XML structure could be a possible solution, but in this case you may find yourself overcomplicating things, template layer was made for presentation, don't put too much logic into it:
We see a template system as a tool that controls presentation and
presentation-related logic – and that’s it. The template system
shouldn’t support functionality that goes beyond this basic goal.
Parse the XML in the view, make a list of dictionaries and pass it to the template inside the context.
For example, use xmltodict tool:
persons = xmltodict.parse(data)['root']['person']
where data is your XML structure.
I'm working with Django and in the base template I see this: {% get_cms_html_fragment "html/footer" %}
From the surrounding syntax I can easily conclude that this is a footer include of some sort. But, it doesn't follow the traditional syntax of {% block headerexample %}{% endblock %} that is normally used in Django templates. Does anyone recognize this?
In Django you can easily create custom tags. So it can be this very project specific tag.
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/
This is a syntax for a template tag. FYI, block is one of the built-in template tags, get_cms_html_fragment is a custom one.
Custom template tags and filters are loaded via load built-in template tag.
See also:
Django: what does "load" do (in a template file)?
I know Django has already a good templating system for designers but I wonder if it is possible to limit the usage of certain template tags and filters.
We are building a Django plugin for designers to make template developing more open, but we want to hide some logic of django template system and expose just the necessary to the designer.
In example: How can I prevent the use of {% load %} template tag and preload only the tags that I want?
Try this decorator: Safe template decorator
From author description:
A decorator that restricts the tags and filters available to template
loading and parsing within a function.
This is mainly meant to be used when granting users the power of the
DTL. You obviously don't want users to be able to do things that could
be potentially malicious.
The {% ssi %} tag, for example, could be used to display sensitive
data if improperly configured.
{% load %} gives them access to all the unlimited python code you
wrote in your templatetags. {% load sudo %}{% sudo rm -rf / %} o_0
Note that the "load" tag (among others) is not listed in the default
tag whitelist. If you parse a template (however indirectly) in a
function decorated with this, unlisted builtin tags will behave like
undefined tags (ie, they will result in a TemplateSyntaxError).
Since {% load %} is not whitelisted, you may want to include some
custom tags or filters as "builtins" for convenience. Simply put the
module paths to the libraries to include in the extra kwarg or the
extra_libraries list. Generally, this is not recommended, as these
libraries need to be carefully and defensively programmed.
NOTE: This does not do anything about cleaning your rendering context!
That's completely up to you! This merely restricts what tags and
filters are allowed in the templates.
Examples:
from django.template.loader import get_template
safe_get_template = use_safe_templates(get_template)
tmpl = safe_get_template('myapp/some_template.html')
from django.template import Template
use_safe_templates(Template)('{% load sudo %}')
# TemplateSyntaxError: Invalid block tag 'load'
An easy way would be to implement your own template loader similar to Django's file system loader and strip certain tags out of the text (guess you could event turn into a template/template nodes when doing so to be able to parse it correctly) before giving the template to Django for further processing.