For example, I have a template file called:
filter.html
{{ title }}
code...
What I'd like to do is, on a separate template:
{% with "Filter by Types" as title %}
{% include "filter.html" %}
{% endwith %}
Currently it can't be done. Could someone explain why that is and an alternative way to achieve this?
Background context:
The app base is used for multiple sites. The site admin would only be able to edit the template files to give them a degree of customization, but not the views.py or other core files. So the {{ title }} variable can't really be sent by the views.py.
I might be missing something but why not just use extends and block tags?
base.html
{% block title %}Default title{% endblock %}
filter.html
{% extends "base.html" %}
{% block title %}Filter by Types{% endblock %}
Check out the documentation on extends, blocks and template inheritance for more info.
Related
I was wondering, when using templates in django, I'm able to extend other base templates and override some of the blocks in the base template. so my question is when I override, would the code in the overridden block still get rendered then overridden, or would it never be run and only the new block is rendered?
Example:
base.html
{% block menu %}
{% for option in menu %}
...Create the menu entries
{% endfor %}
{% endblock menu %}
extender.html
{% extends base.html %}
{% block menu %}
... some other tags
{% endblock menu %}
In this case does the original for loop in the base.html run if it gets overridden?
As far as I know the block will be overwritten unless you want to preserve its code in your extended template.
If you want to preserve the original block you can use {{ block.super }}
base.html
[...]
<body>
{% block header %}
base header content
{% endblock %}
[...]
</body>
extended.html
{% extends "base.html" %}
{% block header %}
{{ block.super }}
new content added
{% endblock %}
[...]
G.
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 try to modify django admin templates
I created custom template with the name corresponding to template, that I want to override.
I try the following
{% extends "admin/change_form.html" %}
<h1>HELLO</h1>
If I reload the page I dont see h1 tag.
If I try
{% extends "admin/change_form.html" %}
{% block field_sets %}
<h1>HELLO</h1>
{% endblock %}
I seen only h1 tag and dont see model's editing fields.
What have I do to see form and h1 tag in same time ?
This should work:
{% extends "admin/change_form.html" %}
{% block field_sets %}
{{ block.super }}
<h1>HELLO</h1>
{% endblock %}
You must call the block from the source change_form.html template. Do that with {{ block.super }} as shown above. You can, of course, reverse the order between super and h1 according to your needs.
It seems like the 'with' tag is not working if it is declared outside of a block as this:
{% extends 'base.html' %}
{% with my_var=1 %}
{% block test1 %}
{{my_var}}
{% endblock %}
{% block test2 %}
{{my_var}}
{% endblock %}
{% endwith %}
The template above simply displays nothing since my_var is NOT passed inside those blocks.
How can I overcome this?
I came to Django from using Tornado with Jinja2 and I was being driven insane by the inability to set variables that (a) could be defined in the template (not view) and (b) would be available in the base template that this derives from. Looking at a little four-line piece of code from django-libs, I was able to rig up something like this that worked well. Here is an example of a title string that should appear in various blocks.
settings.py -- add to TEMPLATES (Django 1.10+)
TEMPLATES = {
...
builtins = ['mysite...wherever...templatetags',]
}
mysite.whereever.templatetags.py
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def setvar(context, key, value):
context.dicts[0][key] = value
return ''
base.html
{% block settings %}
{% comment %}
Put this at the TOP of the template before
any blocks that use variables.
{% endcomment %}
{% endblock settings %}
<html>
<head><title>{{title}}</title></head>
<body><h1>My Site: {{title}}</h1>
{% block body %}
{% endblock body %}
</body></html>
menu.html -- a template that does not set 'title' in views:
{% extends "base.html" %}
{% block settings %}
{{ block.super }} {% comment %}optional{% endcomment %}
{% setvar 'title' 'Menu' %}
{% endblock %}
{% block body %}
<ul><li>Fish</li><li>Steak</li></ul>
{% endblock %}
Now the title will appear in two places in the HTML even though it is defined in the derived template but appears in the top template.
I would like to know how could I add some logic on my admin dashboard. I need to make queries on three different models and show data on Dashboard template but still can't handle the template extention with different models data.
Thanks!
Accomplishing what I was planning to do looked weird. I would need to change the base_site.html rendering view to show up these information, or something else that I don't know how to deal with, so, what i did was:
Extend admin/base.html on /templates/admin loading original data, and overriding some blocks
{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}
{{ title }}
{% endblock %}
{% block branding %}
<h1 id="site-name">Administration</h1>
{% endblock %}
{% block nav-global %}
<center>
<button>Reports</button>
<button>Graphs</button>
</center>
{% endblock %}
It's working fine by now, but still don't know how to deal with admin view of base_index.html