I am having the Issue with Jinja2 Extend and Import.
base_admin.html
<html>
<body>
<div class="outerbody">
<somehtml code>
{% include "base_admin_nav.html" %}
{% include "base_admin_sidebar.html" %}
{% include "base_admin_content.html" %}
</div>
</body>
</html>
base_admin_content.html
<div class="innerbody">
{% block body_content %}
{% endblock %}
</div>
admin.html
{% extends 'base_admin.html' %}
{% block body_content %}
<div>BodyContent</div>
{% endblock %}
The code inside body_content is not passed to base_admin_content.html. Any workarounds?
Note
This is not duplicate of this one
jinja2: blocks in included files..
The include is done in different files here
Defining {% macro admin_content() %} insdide base_admin_content.html and importing it inside base_admin.html using
{% from "base_admin_content.html" import admin_content with context %}
{{ admin_content() }}.
also has no effect.
Edited - to reflect changes in original question
Ok, now that I know you definitely need the includes, here's how I would do it: instead of including the base_admin_content.html file, you should include the admin.html file directly into base_admin.html. The admin.html file will extend base_admin_content.html and everything should work just fine:
base_admin.html
<html>
<body>
<div class="outerbody">
<somehtml code>
{% include 'admin.html' %}
</div>
</body>
</html>
admin.html
{% extends 'base_admin_content.html' %}
{% block body_content %}
<div>BodyContent</div>
{% endblock %}
base_admin_content.html
{% block innerbody %}
<div class="innerbody">
{% block body_content %}
{% endblock %}
</div>
{% endblock %}
Why does this work but your original code does not?
In your base_admin.html file you have
{% include 'base_admin_content.html' %}
Where we have no reference to admin.html, which is why nothing from the admin.html file shows up!. Therefore, we should do this:
{% include 'admin.html' %}
Because that does contain a reference to base_admin_content in the extends line:
{% extends 'base_admin_content.html' %}
Hopefully that makes sense...
You could inherit from base_admin and base_admin_content separately:
base_admin.html:
<html>
<body>
<div class="outerbody">
...
{% block admin_content %}
{% include "default_admin_content.html" %}
{% endblock %}
</div>
</body>
</html>
base_admin_content.html: (unchanged)
<div class="innerbody">
{% block body_content %}{% endblock %}
</div>
admin.html:
{% extends 'base_admin.html' %}
...
{% block admin_content %}
{% include "admin_content.html" %}
{% endblock %}
admin_content.html:
{% extends 'base_admin_content.html' %}
{% block body_content %}
<div>BodyContent</div>
{% endblock %}
This way base_admin doesn't need to know about base_admin_content's blocks,
it's flexible and simple.
Related
I'm trying to load different html files into the base.html and they're not showing. Any ideas?
<body class="bg">
<main class='text'>
{% block carousel %}
{% endblock %}
{% block info%}
{% endblock %}
{% block content %}
{% endblock %}
{% block mobile %}
{% endblock %}
</main>
</body>
I think you may be confusing template inheritance with template composition.
In template inheritance, you have a base page like base.html:
<body class="bg">
<main class='text'>
{% block carousel %}
{% endblock %}
{% block info%}
{% endblock %}
{% block content %}
{% endblock %}
{% block mobile %}
{% endblock %}
</main>
</body>
Then, you have a second template shoes.html that extends base.html. It inherits all the HTML from base.html, but fills in some custom content inside the blocks:
{% extends "base.html" %}
{% block carousel %}
<p>Carousel</p>
{% endblock %}
{% block info%}
<p>Info</p>
{% endblock %}
{% block content %}
<p>Content</p>
{% endblock %}
{% block mobile %}
<p>Mobile</p>
{% endblock %}
Therefore, when you render it inside your view:
views.py
from django.shortcuts import render
def index(request):
return render(request, 'polls/shoes.html', {})
you get this result:
<body class="bg">
<main class='text'>
<p>Carousel</p>
<p>Info</p>
<p>Content</p>
<p>Mobile</p>
</main>
</body>
I suspect that you have different HTML files named after each block (e.g. carousel.html, info.html). That's not how Django works (but it is how Ruby on Rails works). Is that what you were trying to do? If not, please update your question to clarify.
I have base.html and file with header _header_main.html in my main template index.html i extends base.html and include _header_main.html but variables that i pass into index.html not visible in parent template
base.html:
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<!-- styles -->
...
</head>
<body>
{% block _header_main %}{% endblock %}
{% block _header_mobile %}{% endblock %}
<div class="wrapper">
<!-- header -->
{% block header_main %}{% endblock %}
{% block header_mobile %}{% endblock %}
<div class="after_header"></div>
<!-- end header -->
{% block content %}{% endblock %}
<footer class="footer">
...
</footer>
</div>
</body>
</html>
_header_main.html:
<header class="header">
<ul>
{% for i in servers %}
<li>{{ i.title }}</li>
{% endfor %}
</ul>
</header>
index.html:
{% extends "base.html" %}
{% load static %}
{% block title %}Title{% endblock %}
{% block header_main %}
{% include "_header_main.html" %}
{% endblock %}
{% block content %}
Some content...
{% endblock %}
<scripts>
...
</scripts>
How i can access to variables items in my template?
Edit. My function in views.py
def index(request):
servers = Server.objects.all().order_by('ranking')
basket_count, total_price = basket_calculate(request)
server_arr = [i.title for i in servers]
servers_string = ', '.join(server_arr)
return render(request, 'index.html', {'servers':servers, 'temp_year' : datetime.now().year,
'basket_count':basket_count, 'total_price':total_price,
'servers_string':servers_string })
The reason why my items variable don't show in templates, is because i add <script> tag with js without block, so my scripts didn't work. I add my scripts to {% block script %} and all works fine!
Hello i am newbie in Django, started to learn it today and i have problem with template inheritance
i have such function in my view:
def show(request, id=1):
return render_to_response('template1.html', {
'name': name,
'model1': Model1.objects.get(id=id),
'model2': Model2.objects.get(id=id).model1,
})
And i have 3 different templates, main.html with such code:
<body>
{% block block1 %}
{% endblock %}
{% block block2 %}
{% endblock %}
</body>
</html>
and two more tempaltes that contains code like that:
{% extends 'main.html' %}
{% block block1 %}
<h2>{{ var }}</h2>
<pre>{{ var }}</pre>
{% endblock %}
second one is very similar so i wont show it, problem is: i dont know which one to put in render_to_response function.
if i put main.html:
return render_to_response('main.html', {
it doesn't load any templates, but content from main.html appears well, i can just see empty space on page
if i put template1:
return render_to_response('template1.html', {
It load only content from main and from template1.html but i need content from template2.html
if i put template2.html to function it only shows content from main.html and from template2.html but no content from template1.html
Please help me how to solve that problem.
Option 1) Try using the {% include %} tag.
main.html
<head> ... </head>
<body>
{% block content %}
{% endblock content %}
template1.html
{% extends "main.html" %}
{% block content %}
<h1>Hello world</h1>
{% include "nested_template2.html" %}
{% endblock content %}
nested_template2.html
<p>The world is smaller than you think.</p>
In your view/controller:
return render_to_response('template1.html', {
Option 2) Chain {% extends ... %} tags as deep as you want. I frquently use this structure:
templates/
----base.html
----projects/
----_.html
----detail.html
----list.html
The base.html is the master layout. The folder/_.html is specific to a "stage" (more modular content).
base.html
<head> ... </head>
<body>
{% block stage_content %}
{% endblock stage_content %}
projects/_.html
{% extends "main.html" %}
{% block stage_content %}
<h1>Project Stage</h1>
{% block page_content %}
{% endblock page_content %}
{% endblock stage_content %}
projects/list.html
{% extends "projects/_.html" %}
{% block page_content %}
{% for project in projects %}
<li>{{ project.name }}</li>
{% endfor %}
{% endblock page_content %}
projects/detail.html
{% extends "projects/_.html" %}
{% block page_content %}
Viewing project {{ project.name }}
{% endblock page_content %}
In your view/controller:
return render_to_response('projects/detail.html', {
I am currently in the process of adding a theme to the admin of django one issue I have found it adding styling to the forms is that it is very difficult and I can't find much useful documentation on it. The only real thing I need to do is add classes to the form elements so that they match the theme I am using is this possible and if so how would you go about doing it the code I am currently using is very basic and the basic code included in the standard theme does anybody know how to add classes to these standard bits of code bellow is what I have.
{% if is_popup %}
<input type="hidden" name="_popup" value="1" />
{% endif %}
{% if save_on_top %}
{% block submit_buttons_top %}
{% submit_row %}
{% endblock %}
{% endif %}
{% if errors %}
<p class="errornote">
{% blocktrans count counter=errors|length %}
Please correct the error below.
{% plural %}
Please correct the errors below.
{% endblocktrans %}
</p>
{{ adminform.form.non_field_errors }}
{% endif %}
{% block field_sets %}
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
{% endblock %}
{% block after_field_sets %}{% endblock %}
{% block inline_field_sets %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
{% endblock %}
{% block after_related_objects %}{% endblock %}
{% block submit_buttons_bottom %}
{% submit_row %}
{% endblock %}
There are a lot of ways to do this, but certainly one way would be to overwrite all the widgets in your ModelAdmin rather than in the template. That could look something like this:
from django.db import models
from django.contrib import admin
from django.forms.extras.widgets import TextInput
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': TextInput(attrs={'class':'my-widget-class'},)},
}
You'd have to go through and do that for each widget, but then they'd have the appropriate classes -- at least for that modelAdmin.
I'm wondering if anyone knows how to deal with the following quirky template structure:
### base.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title> {% block title %} Title of the page {% endblock %} </title>
</head>
<body>
<header>
{% block header %}
{% include "base/header.html" %}
{% endblock header %}
</header>
{% block content %}{% endblock %}
</body>
</html>
### base/header.html
<div id="menu-bar">
{% block nav %}
{% include "base/nav.html" %}
{% endblock %}
</div>
### base/nav.html
<nav id="menu">
<ul>
<li>
My Profile
</li>
<li>
My Favorites
</li>
{% block extra-content %}{% endblock %}
</ul>
</nav>
And, the heart of the matter:
### app/somepage.html
{% extends "base.html" %}
{% block content %}
<p>Content is overridden!</p>
{% endblock %}
{% block extra-content %}
<p>This will not show up, though...</p>
{% endblock %}
{% block nav %}
<p>Not even this.</p>
{% endblock %}
The problem is when extending a template you can only override the blocks declared in the parent only, not any of its children.
I suppose I could make base.html a husk of empty unused nested blocks covering all future contingencies, but would even that override properly? And is that the only way?
If you're wondering why I have a bi-directional include/extends workflow around base.html, I have many sub-templates that I want to get used all across the project: Headers, footers, navs, sidebars, etc. They all will be consistant in structure across the entire site, but in many cases a whole subdivision of the site will only need a few of those sub-templates. My idea was to define the sub-templates under the templates/base folder, and have templates/base-type1.html, templates/base-type2.html, etc to extend in other places. Each type would only reference the sub-templates needed, and override them to place content as needed.
It seems to be little known that you can use the with keyword with the include to pass variables into the context of an included template - you can use it to specify includes in the included template:
# base.html
<html>
<body>
{% block header %}{% include "header.html" %}{% endblock %}
</body>
</html>
# header.html
# some stuff here
<div id="header">
<img src="logo.png">
{% include nav_tmpl|default:"navigation.html" %}
</div>
# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
{% include "header.html" with nav_tmpl="special_nav.html" %}
# you might also want to wrap the include in an 'if' tag if you don't want anything
# included here per default
{% endblock %}
This approach saves you at least from having one additional file just for the purpose of overwriting a block. You can also use the with keyword to pass a value through a bigger hierarchy of includes as well.
A terser variant to the solution proposed by #Bernhard Vallant:
# base.html
<html>
<body>
{% block header %}{% include "header.html" %}{% endblock %}
</body>
</html>
# header.html
# some stuff here
<div id="header">
<img src="logo.png">
{% include nav_tmpl|default:"navigation.html" %}
</div>
# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
{% with nav_tmpl="special_nav.html" %}
{{ block.super }}
{% endwith %}
{% endblock %}
You can solve this by extending your currently-included templates, then including the extension instead of the the currently-included base template.