Passing variables to a Django template extended by several views - django

I have a Django template base.html that I extend in several views. Each view adds a content block and provides the information needed to render that block.
Now I want to change base.html to show some system status information. Does this mean I need to update every single view to request this info from the DB and pass it into the template, or is there some better way to do it?
base.html
<body>
<div>
{{ system.status }}
</div>
<div>
{% block content %}
{% endblock %}
</div>
</body>
view1.html, view2.html, view3.html, etc.
{% extends 'base.html' %}
{% block content %}
<div>
{{ view_specific.info }}
</div>
{% endblock %}
Should every view be made to provide the system object?

Thanks Daniel Roseman, solved it with a custom inclusion tag.

Related

How to use JavaScript in included components in Django?

In short, how to use JavaScript in the component that will be then included in the main page?
A standard approach in Django templates is to create a base.html template and then extend it. That base template usually has blocks like content, extra_js, and extra_css. The extended template looks like
{% extend 'base.html' %}
{% block content %}
<div>
some content
</div>
{% endblock %}
{% block extra_js %}
# some js code here
{% endblock %}
I need to create a component that will be included on several pages and I need to use JavaScript inside that component. I know that it will be included only on pages that extend base.html, the page that includes it will look like
{% extend 'base.html' %}
{% block content %}
<div>
{% include 'component.html' %}
</div>
{% endblock %}
{% block extra_js %}
# some js code here
{% endblock %}
However, component.html knows nothing about extra_js block because it doesn't extend base.html, I cannot use that block in component.html, and if I just put some JavaScript code in it then after the template is rendered any JavaScript in component.html will end up being in the middle of the body of the document, will be executed before libraries like jQuery are imported and will not work. What is the right way to work around it?

Django: Frequent use of include template tag - how much is too much?

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 %}

Is it possible to use a block tag ({% block %}) from base html template two or more times in derived html file in Django

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.

How can I override an inherited container in Django templates?

I have a base template like this.
base.html
<div class="container">
{% block content %}
{% endblock content %}
</div>
The problem is in a few pages that inherit from it (i.e., extend base.html ) I don't want the outer container around the content. Is there anyway to achieve this?
If you can change a bit your base.html template
{% block content_wrapper %}
<div class="container">
{% block content %}
{% endblock content %}
</div>
{% endblock content_wrapper %}
Then in your few specifics template you can override the content_wrapper block.
The easiest way as I see it is to create another base template that you extend. Perhaps calling it base-purpose.html. Another way could be to use the {% include 'another.html' %} tag. This might be able to solve your problem as well.
See the discussion between include and extend on stackoverflow

Overriding django admin dashboard and adding logic on it

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