DRY method to add a class to <body> in the base template? - django

This is the general structure of my base.html:
<html>
<head>
</head>
<body class="noscroll">
<nav class="navbar navbar-static-top navbar-dark bg-inverse">
</nav>
{% block content %}
{% endblock content %}
</body>
</html>
On certain pages, I want the noscroll class which is essentially overflow-y: hidden; but I also have pages that require the scroll. I could move the navbar into its own snippet and insert that, but such a method seems unsatisfactory. Or I could make a separate base_noscroll.html, but that may lead to inconsistencies, so I would have to nest two templates which again would become unsatisfactory.

Just add an override-able block with the default content:
<body class="{% block body_class %}noscroll{% endblock %}">
then the noscroll class is there, or you can override it in a template that extends base.html. Django template blocks can go nearly anywhere; they don't have to wrap entire HTML tags.
If you find yourself overriding this block a lot, you can always just add another template that extends base.html and does the override, then extend that:
# noscroll.html
{% extends 'base.html' %}
{% block body_class %}{# empty to override #}{% endblock %}
Then in subsequent pages you can extend either template. How much flexibility you need is always up to you.

Related

using Django "include" template tag as nested - side effects?

Does anyone know or have any experience about bad side effects of using "nested include tags"?
(I mean including a template file which itself includes another template)
For example:
file x.html:
{% include "z.html" %}
file y.html:
{% inclide "x.html" %}
Bad side effects are messed up CSS rules and some headache while debugging. It is generally better to keep them rather flat.
x.html:
{% extends "_base.html" %}
{% block main_content %}
<h1>I am X</h1>
{% include "includes/z.html" %}
{% endblock main_content %}
y.html:
{% block main_content %}
<h1>I am Y</h1>
{% include "x.html" %}
{% endblock main_content %}
z.html:
<h2>I am Z</h2>
Check the code:
https://github.com/almazkun/templating
I think you are confusing include and extends
Logically, extending a template when used in the likes of a base.html is great, and if you design your templates in a way which allows you to extend certain base html files for certain sections of your site. This is generally when they have shared snippets of html, like the main css block, meta block, script block etc..
You can extend n number of times.
Where you are getting confused with include, is that this is more for including snippets of code which are additive or sort of "drop-in" and great examples would be sidebars, navbars, and even custom css or javascript!
The question is, do you want to shared html snippets, or do you want to add extra snippets to certain sections but not others?
If its the latter, you'll want include, and for the former, you'll want extends.
Edit #1:
You have asked for clarity regarding the drawbacks of the two aforementioned template tags. As I sit here and ponder that question, I cant think of any significant disadvantages of using either include or extends providing that you have used them where they should be used. If you have used an include, where actually you should have used extended the template, you may find, as is described in someone else's answer, that css rules may not be applied in the way you would expect them to be.
The question is about nested include tags and the answers show that "there is no actual problem if you know what you expect and how to handle it".
There is a paragraph in the docs about the include tag that sets some limits, nonetheless:
The include tag should be considered as an implementation of “render
this subtemplate and include the HTML”, not as “parse this subtemplate
and include its contents as if it were part of the parent”. This means
that there is no shared state between included templates – each
include is a completely independent rendering process.
Trying to make ends meet about rendering and parsing:
https://stackoverflow.com/a/35966477/2996101
Shared state between included templates is a complicated issue even for big front end frameworks, such as React.
No problem! It's usual to use inheritance in Django templates. You can make a template with some blocks and override blocks in children templates and children of children can override or use superblock content.
I didn't have any issues chaining include. You might have issues if have extend or blocks with similar names in the included template.
There are no issues when you include a number of templates.
for example
base.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
{% block title %}{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
-->
</body>
</html>
a.html
<h1>I am from A</h1>
b.html
<h2>I am from B</h2>
c.html
{% extends 'base.html' %}
{% load static %}
{% block title %}<title>Welcome in C!</title>{% endblock %}
<h3>I am from C . I am mother of A and B </h3>
{% block content %}
{% include 'a.html' %}
{% include 'b.html' %}
{% endblock %}

How to create reusable components for UI in Django

I am building a project in Django which has 5 different applications inside it. Some applications are falling under same pattern and some are not. Can I create a UI components using bootstrap on the top of all these applications to reuse over the entire project. Any help would be appreciated.. Thanks in advance
Usually that is done by creating a base template and making other templates inherit from it like this:
base.html
<html>
<head>
<title>Title</title>
</head>
<body>
<navbar> # example navbar that will be visible in each template that will extend this one
<ul>
Home
Contact
Something else
</ul>
</navbar>
{% block content %} # here is where the content of child templates will be seated
{% endblock %}
</body>
</html>
then you will make any other template and extend it with base.html
your_other_template.html
{% extends 'base.html' %} # this line makes sure your child templates inherit the html of your main template
{% block content %} # here is where you will place the content of your other templates
<h1> This is the content of a child template </h1>
{% endblock %}
Paste your component in an empty html file and then use an include statement to load that file into you template html.
https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#include
This way you can insert you components more dynamically throughout your project.

Django templates, including page(s) that injects code into parent block

Is it possible to include a template (with include django template tag) within another template and "inject" some content to the page that includes (parent) through block tag, or something similar?
Let's say I have the following file structure within my project:
App/
(...)
templates/
base.html
index.html
_include1.html
_include2.html
_include3.html
_include4.html
Code for base.html:
<!DOCTYPE html>
<html>
<head lang="en">
(...)
</head>
<body>
<script type="application/javascript">
$(function () {
{% block extra_script %}
{% endblock %}
});
</script>
Code for index.html:
{% extends "base.html" %}
{% load static %}
(...)
<div class="row gutter">
<div>
{% include "_include1.html" with object=object%}
</div>
<div>
{% include "_include2.html" with object=object %}
</div>
<div>
{% include "_include3.html" with object=object %}
</div>
<div>
{% include "_include4.html" with object=object %}
</div>
</div>
And in each _include*.html I would like to call some specific JS function (for example), but I want to place it in the parents (index.html or base.html, doesn't matter in my case) extra_script block. I searched in the documentation, other questions and didn't find a way to do this with the include syntax.
I've done something similar but through extends tag. However I don't want to define a block in the index.html or base.html for each page that I need to include ({% bloc include_* %}.
So the solution that I have now (and works) is to define a script in each included page like this (_include1.html):
<div>
(...)
</div>
<script>
$(function () {
//Code that should be placed within parents script page (this is just an example)
var a = function (){
(...)
};
a();
});
</script>
However I think there's a better way to do this, by making use of django templates engine, and without having to define a block for each page that needs to be included. Also I would like to have all my js code in a single place (parents <script> tag) instead of being scattered all over the place (like it is with the presented solution).
Can anyone give some input or ideas towards this?
Thanks!
Try to use django-sekizai for that purpose.
With sekizai, you can define a JavaScript block just before the </body>:
{% render_block "js" %}
And then whenever you need to add JavaScript to that block, you write this:
{% addtoblock "js" %}
<script type="text/javascript">
// your JavaScript
</script>
{% endaddtoblock %}
If there are duplicates of the content in the {% addtoblock %} blocks, they will be used only once.

Django static file inheritance

Perhaps I'm coming at my problem with a WordPress mindset but what i'd like to achieve is the notion of a parent/child theme for Django projects. I think I can solve the template issue by defining two template directories
TEMPLATE_DIRS = (
'/home/Username/webapps/django/child/templates',
'/home/Username/webapps/django/parent/templates',
)
But is there a way to achieve this with the static files? For example, we add a new feature to the parent, update the parent app which updates the templates along with adding some new javascript, LESS, and images.
You don't need to specify two template directories. There is a concept of parent and child templates. All child templates extends the parent:
base.html (we often use this name for parent)
<html>
<head>
<!-- Some css, js stuff goes here-->
{% block extra_head %}
<!-- A block where child templates add more css and js stuff if needed -->
{% endblock extra_head %}
</head>
<body>
{% block body %}
<!-- body content here -->
{% endblock body %}
</body>
</html>
And then child template will extend the base.html as:
child.html
{% extends "base.html" %}
{% block body %}
<h1>Hello!</h1>
{% endblock body %}

How to call several addOnLoad functions in dojo?

I'm trying to define several dojo elements from several (inherited) HTML pages , and each defines addOnLoad of his own, which causes only the latest function to be executed, since they are overridden.
Is there a way to overcome this problem?
Thanks.
You can use blocks to replace inherited elements
in template-base:
<head>
<script type="text/javascript" src=""></script>
{% block extra-header %}
#code default
...
{% endblock %}
</head>
in template:
{% block extra-header %}
{{ block.super }}
#replacement code
...
<script type="text/javascript" src=""></script>
{% endblock %}
for more information see https://docs.djangoproject.com/en/1.3/topics/templates/#template-inheritance