Django template include overwrite <h1> tag - django

I have the following html files.
banner.html
<header class="intro2">
<div class="intro-body">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>{% block banner %}Bannertest{% endblock banner %}</h1>
</div>
</div>
</div>
</div>
</header>
test.html
{% extends 'banner.html' %}
{% block banner %}
Test
{% endblock banner %}
I'm new to Django but I would expect the H1 title to be updated to say Test instead of Bannertest?
What am I doing wrong?

You need to extend your main html not to include
replace
{% include 'banner.html' %}
to
{% extends "banner.html" %}
more details here: include-vs-extends
your full new html:
{% extends 'banner.html' %}
{% block banner %}Test{% endblock banner %}

For block overriding you must use {% extends 'banner.html' %} instead of {% include %}
So instead of making small fragments for include, like in php, standard approach is to make a full template, say base.html, when extend it in child templates.
{% include %} tag is better suits for widgets with parameters, e.g. {% include '_form.html' style='light' some_param=some_value %}

Related

Djang multiple levels of template extension while keeping the elements of the upper levels

I have 3 templates as following:
base.html (the top level template, as usual).
<body>
<div id="header">
...
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
category.html :
{% extends "base.html" %}
{% block content %}
<div class="category_row">
<div id="menu_category_display">
{% for category in menu_categories %}
{% with category_button="menu_"|add:category.name|lower %}
<button class="button category_buttons {{category_button}}"
onclick="showItem('{{category_button}}','category_buttons')">
{{category}}
</button>
{% endwith %}
{% endfor %}
</div>
</div>
<div class="item_row">
{% block level_2_content %}
{% endblock %}
</div>
{% endblock %}
and item.htlm
{% extends "menu/category.html" %}
{% block level_2_content %}
<div id="test_div">
{% for item in menu_items %}
<p>{{item.name}}</p>
{% endfor %}
</div>
{% endblock %}
When item.html is rendered, all the elements that were rendered by category.html are gone. Only the elements of the base.html are retained.
How do I retain all elements in all parent templates instead of just base.html? A general method to do this for more than 3 levels of extension like in my case?
Update with more detailed code for category.html. The entire category_row div does not appear in item.html. How do I retain them?
views.py
def menu_category_view(request, table_pk):
menu_categories = Category.objects.all()
menu_items = Item.objects.filter(available=True)
return render(request,
'menu/category.html',
{'menu_categories': menu_categories,
'menu_items': menu_items,
'table_pk': table_pk})
def menu_item_view(request, menu_category, table_pk):
category = Category.objects.get(name=menu_category)
menu_items = Item.objects.filter(available=True,
category=category.pk)
return render(request,
'menu/item.html',
{'menu_items': menu_items})
Folder structure: both templates sit in menu/templates/menu of app menu. However, base.html sits in root/templates (not in app menu.
Update: I have tried modifying both templates in various ways to debug. What I find is that the static content gets extended, but the dynamic content does not. So my question becomes: does Django template allow dynamic content to be extended to child / grandchild templates?
You probably don't want to use "extends" here but instead "include" to render 'item.html' within the parent document.

No content visible in django-bootstrap3

I am using Django 1.9 and demo template structure to display home.html.
I have included the following in the base.html file:
{% block bootstrap3_content %}
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
...
</div>
</nav>
<div class="container-fluid">
{% autoescape off %}{% bootstrap_messages %}{% endautoescape %}
{% block content %}(no content){% endblock %}
</div>
{% endblock %}
Navbar shows successfully but I do not get the Bootstrap message in the container below?
I am a new user to Django and this App as well. Please help!
Edit1:
bootstrap.html extends bootstrap3.html; base.html extends bootstrap.html; home.html extends base.html.
home.html
{% block title %}My_title{% endblock %}
{% block content %} This is <em>bootstrap3</em> for <strong>Django</strong>.
{% endblock %}
I get the title in the navbar but no message inside content block.
Make sure that you have
{% load bootstrap3 %}
at the top of your page since you are using this module. Make sure that you have
'bootstrap3',
in your installed apps.
From your code it looks like you are extending a template. If you are, be sure to have a
{% extends FooTemplate.html %}
in case you are loading boostrap3 in the parent template.

How to make a reusable template in Django?

What is the Django way of creating a reusable template?
Example: Suppose a lot of my pages contain a "Latest News" box and following the DRY principle, I would like to define it once and reuse it in the other pages. How would I do this with Django (or Jinja2) templates?
Reading through Django's Template Documentation I get the impression that Django templates offer "top-down" inheritance where the sub-template itself determines in which super-template it is going to be embedded:
<!-- Super-template (not valid, for illustration): -->
<html>
<head><title>Title</title></head>
<body>{% block content %}{% endblock %}</body>
</html>
<!-- Sub-template: -->
{% extends "base.html" %}
{% block content %}
<div class="latest-news">News</div>
{% endblock %}
So what is the technique to reuse a block (a sub-template) in several places?
The most flexible way to reuse template fragments is to define an inclusion_tag. You can pass arguments to your custom tag, process them a bit in Python, then bounce back to a template. Direct inclusion only works for fragments that don't depend on the surrounding context.
Quick example from the docs:
In app/templatetags/poll_extras.py register the tag with a decoration:
from django import template
register = template.Library()
#register.inclusion_tag('results.html')
def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}
In app/templates/results.html:
<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>
Calling the tag:
{% load poll_extras %}
{% show_results poll %}
What you're looking for, is {% include "template.html"%} from Django docs.
If you need to use {% block %} you can only do that via the {% extend %} approach. Otherwise, you can use {% include 'some.html' %} to include a bit of HTML in multiple places.
The unofficial Django Reusable App Conventions recommends using these block names:
{% block title %}
{% block extra_head %}
{% block body %}
{% block menu %}
{% block content %}
{% block content_title %}
{% block header %} {% block footer %}
{% block body_id %} {% block body_class %}
{% block [section]_menu %} {% block page_menu %}
If everyone stuck to these conventions, it should make this problem easier. Follow the link to see the description of each block.
Example of using {% include %} tag
All data comes from Django back-end
Many values are passed to card_template.html using include tag in page1.html
card_template.html
<style>
.choices_div {
border-radius: 5rem;
}
.card-footer {
background-color: transparent;
border: transparent;
}
</style>
<div class="col mb-5 px-4">
<div class="card h-100 w-100 jumbotron choices_div {{ bg_color|default:'' }}">
<div class="card-body p-0">
<h3 class="card-title text-center">{{ card_title|capfirst }}</h3>
<ul class="card-text mt-3">
{% for c in card_body_list %}
<li>{{ c }}</li>
{% endfor %}
</ul>
</div>
<div class="card-footer text-center pt-4">
{% if get_post_request == 1 %}
<a class="btn btn-light" href="{{ href }}">{{ button_text }}</a>
{% else %}
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-light w-75" name="category"
value="{{ button_value }}">{{ button_text }}</button>
</form>
{% endif %}
</div>
</div>
</div>
page1.html
{% extends 'core/core.html' %}
{% block body %}
<div class="jumbotron bg-white">
<div class="container">
<div class="mb-5 text-center">
<h1>Choose user category</h1>
<h5>Once choosen, the user category cannot be changed</h5>
</div>
<div class="row row-cols-lg-2 justify-content-around">
{% for object in object_list %}
{% cycle 'bg_peacock' 'bg_sunset' 'bg_skin' 'bg_brown' as bg_color silent %}
{% include 'core/card_template.html' with card_title=object.category card_body_list=object.description get_post_request=2 button_text='Select' bg_color=bg_color button_value=object.id %}
{% endfor %}
</div>
</div>
</div>
{% endblock %}
As other answers have mentioned, the simplest approach is direct inclusion:
{% include 'mytemplate.html' %}
It is possible to modify the context of the rendered template (Or in simpler terms, to pass variables to the template) using
{% include 'mytemplate.html' with poll=poll %}
To use the traditional polls example, the template I would write would be:
<div class="stylish-poll">
{% for choice in poll.choices %} <!-- poll is a template variable -->
{% include 'choice_template.html' with choice=choice %}
{% endfor %}
</div>
Another potentially useful thing to know is that the only keyword prevents the template variable poll being passed into 'choice_template.html' which it would be by default. If you do not want the choice template to have access to {{ poll }} then the include statement looks like:
{% include 'choice_template.html' with choice=choice only %}
Documentation: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
Aïe, my fault – the answer is given in the Django Reference (and not discussed in the aforementioned Django Template Documentation)…
So: Just use {% include sub_template_name %}.
even though the question is asked years ago, any way I will show you the method that worked for me.
base.html
In your base template you need to define all of your blocks that you need to reuse in your other templates,
<html>
<head>
<meta name="description" content="{%block description%}{%endblock%}">
<meta name="keywords" content="{%block keywords%}{%endblock%}">
<title>{%block title%}{%endblock%}</title>
</head>
<body>
<!---other body stuff--->
{%block content%}
{%endblock%}
</body>
</html>
home.html
{%extends 'base.html'%}
<!--you can reuse all blocks here-->
{%block description%}Django reusable blocks, for every bage{%endblock%}
{%block keywords%}django,block, resuable,meta,title,{%endblock%}
{%block title%}django reuseable blocks for title, meta description and meta keywords{%endblock%}
{%block content%}
<div>
<h1> reuse blocks</h1>
</div>
{%endblock%}

django template extends not working

This is my base.html
<!DOCTYPE html>
<head>
<title> My Site </title>
</head>
<body>
<div id="wrapper">
<!-- HEADER START -->
{% block nav %} {% endblock %}
{% block index %} {% endblock %}
</div>
</body>
</html>
this is my nav.html
{% extends "base.html" %}
{% block nav %}
<div id="header">
<div class="inner">
<div class="nav">
<ul>
<li class="current">Home</li>
<li>About</li>
<li>Blog</li>
<li>Contact</li>
</ul>
</div>
<div class="clear"></div>
</div><!-- .inner end -->
</div><!-- #header end -->
<!-- HEADER END -->
{% endblock %}
this is my index.html
{% extends "base.html" %}
{% block index %}
<p> hello </p>
{% endblock %}
I have done it several times before before but i am clueless as to why this is NOT working?
the urls and views are here.
Well everything is fine, the trouble that you are having is that
you are confused, just naming a block in base does not calls it.
Mark the difference between extends and include.
You have counfused extends to include.
Once in your views if you call say index.html it will be rendered properly.
The effect you want can be achieved by changing the base.html in your views to index.html.
Hope this helps. more can be read here: https://docs.djangoproject.com/en/dev/topics/templates/#template-inheritance
For more people who end up here (as myself), main thing to note is that when you use {% extends 'something.html' %}, you cannot use anything other than these template tags at the top-level.
You can obviously have html tags inside these tags (like block tags), but don't put ANYTHING outside the template tags.
Also helps if you change the path in extends, for example {% extends 'mysite/index.html' %}. And view function must render the file with extends, not the basic one.
In views.py, you have to call the template that extends the other template, not the other way around. In your example you should call nav.html.
try do this
{% extends 'appname/index.html' %}

Pageparts extending templates

Suppose I want to repeat some easy HTML structure on my site a lot of times.
For example, I want to display some parts of the pages "in green boxes".
The first mandatory step to achieve this goal would be to create a template file like this:
<!-- greenbox.html -->
<div style="background-color:#88ff88;"><br>
{% block content %}<br>
{% endblock %}<br>
</div>
Then every time I need this predefined template I have to create a separate template like the following:
<!-- pagepart_1.html -->
{% extends "greenbox.html" %}
{% block content %}
This time I want to add this dummy text in here
{% endblock %}
<!-- pagepart_2.html -->
{% extends "greenbox.html" %}
{% block content %}
The second time I want to add some other text
{% endblock %}
The actual page containing the green boxes will look like this:
<html><head>My Page</head>
<body>
<h1>Page Title</h1>
{% include "pagepart_1.html" %}
<br /><br />
{% include "pagepart_2.html" %}
</body></html>
This kind of approach does work, but I think it contains a little overhead.
Can I avoid the creation of separate templates for each instance (pagepart_1.html, pagepart_2.html, ...)?
So can I make my main page look something like this?
<html><head>My Page</head>
<body>
<h1>Page Title</h1>
{% unkowntag extend "greenbox.html" %}
{% block content %}
This time I want to add this dummy text in here
{% endblock %}
{% endunknowntag %}
<br /><br />
{% unkowntag extend "greenbox.html" %}
{% block content %}
The second time I want to add some other text
{% endblock %}
{% endunknowntag %}
</body></html>
Thanks a lot!
That's the only approach available it you want to allow for completely customizable content areas. However, if you can standardize the content, such that it will always display an unordered list, for example, you can do:
<!-- greenbox.html -->
<div style="background-color:#88ff88;"><br>
<ul>
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</div>
And then in your template:
<!-- mypage.html -->
{% with something as list %}
{% include 'greenbox.html' %}
{% endwith %}
You can do much more complex structures and even pass multiple variables (in Django 1.3+):
<!-- greenbox.html -->
<div style="background-color:#88ff88;"><br>
<h2>{{ title }}</h2>
<img style="float:{{ float }};" src="{{ image }}" alt="{{ alt_text }}">
<p>{{ description }}</p>
</div>
<!-- mypage.html -->
{% with title=obj.title image=obj.image.name alt_text=obj.title float="left" description=obj.description %}
{% include 'greenbox.html' %}
{% endwith %}
I would write a custom tag that emits the HTML and use it multiple times.