Template Inheritance in Nunjucks, what are the requirements? - jinja2

Ok super basic question but I must be missing something.
I render my page:
router.get('/', function(req, res) {
res.render('index.njk', {});
});
Create my base layout, main-layout.njk in layout folder:
<!DOCTYPE html>
<html>
<body>
{% block content %}
{% endblock %}
</body>
</html>
Extend my template, index.njk to add content to the layout:
{% extends 'layout/main-layout.njk' %}
{% block content %}
<?php include_once("analyticstracking.php") ?>
<main>
<p>sploooge</p>
{% block panel %}{% endblock %}
</main>
{% endblock %}
Now I would like index.njk to be extended by panel.njk (the file is in the same folder):
{% extends 'index.njk' %}
{% block panel %}
<p>second sploooge</p>
{% endblock %}
But I cannot get it to appear. The documentation doesn't mention anything but do I need to render it somehow like index.njk?

I believe this issue lies in where you have the 'middle' file.
I got this to work with the following configuration:
File Tree:
pages/
-index.njk
templates/
-base.njk
-layout.njk
base.njk:
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
{% block content %}{% endblock %}
</body>
</html>
layout.njk
{% extends "base.njk" %}
{% block content %}
Content
{% block more %}{% endblock %}
{% endblock %}
index.njk:
{% extends "layout.njk" %}
{% block more %}
More Content
{% endblock %}
Output:
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
Content
More Content
</body>
</html>
You can use a template that is anywhere, you just need to make sure you add that to the url in the extend. Example:
{% extends "templates/layouts/extras/template.njk" %}
This would get horribly confusing and increase the potential for error, but theoretically it would work.
Look into using includes in some areas as well, it may be beneficial in this case to not have an extra layer of templates.

Related

Django template includes + extends

This is my Directory Tree.
base.html:
{% load static %}
<!DOCTYPE html>
<html lang="en">
{% include 'weapons/head/head.html' %}
{% include 'weapons/body/body.html' %}
</html>
body.html:
{% load static %}
<body>
{% block content %}{% endblock content %}
</body>
home.html:
{% extends 'weapons/base/base.html' %}
{% block content %}
<span>Hello!</span>
{% endblock content %}
When I visit my home.html, it doesn't appear to be working correctly. I see nothing on my page, however the "Hello!" message is expected to be shown. What is the problem?
Your base {% block content %} must be in base.html else it won't be usable by home.html.
base.html:
{% load static %}
<!DOCTYPE html>
<html lang="en">
{% include 'weapons/head/head.html' %}
<body>
{% block content %}
{# Leave it empty or add a default content that can be overwritten by other templates #}
{% endblock content %}
</body>
</html>

Twig stylesheets inheritance problem - Symfony 4

As I am working with Symfony 4 and Twig I made a kind of structure to extend templates and include some parts.
I want a frontend and backend page for my project.
Structure:
I included the base/head.html.twig inside the base.html.twig:
The base/head.html.twig this template contains the following:
And now I would like to get a stylesheet specially for the backend:
And this is where the problem is. Because it won't get inherited by the base/head.html.twig.
I have searched the internet for it and tried several things. Maybe you know the answer?
You can use horizontal reuse for this I guess. The setup u'd use should be something like this,
head.twig
{% block head %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Title{% endblock %}</title>
{% block stylesheets %}
<link rel="stylesheet" href="foo.css" />
{% endblock %}
</head>
{% endblock %}
base.twig
{% use 'head.twig' %}
{% block content %} {% endblock %}
actual_template.twig
{% extends 'base.twig' %}
{% block title %}My title{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="bar.css" />
{% endblock %}
{% block content %}
{{ block('head') }} {# inject head.twig in content #}
{% endblock %}
demo

How to insert multiple Django blocks into one template?

I am trying to use more different views in one template via different blocks or include method but I have got stuck. My aim is to implement my different views into one template. I tried to more solution but these haven't worked for me. I show these solution:
My views:
def dashboard_data(request):
# Here I collect data from my PostgreSQL database I push these into
#Objects and I send it to my test_a.html via render like below.
return render(request, 'my_project/test_a.html', send_data)
def chart_data(request):
#In these view my final goal is to collect data from database and create
#charts but for the simplicity I just use a list (a=[1,2,3,4]) and I
#push it to the test_b.html and I render it.
render(request, 'my_project/test_b.html', send_data))
My templates:
1, base.html
<!DOCTYPE html>
<html lang="en">
<head>
{% block title %}<title>My project</title>{% endblock %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Include CSS files -->
{% load static %}
<!-- Include CSS files -->
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'css/bootstrap-table.css' %}">
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
<link rel="stylesheet" href="{% static 'css/font-awesome.min.css' %}">
</head>
<body>
{% block sidebar %}
{% endblock %}
{% block content%}
{% endblock %}
</body>
</html>
1, test_a.html
{% extends "monitor/base.html" %}
{%block content%}
{%for i in table%}
<p> {{i.record}}</p>
{%endfor%}
{%endblock}
2, test b.html
{%for i in a%}
<p> {{i}}</p>
{%endfor}
So my goal would be that the test_b.html's result could appear in the base.html.
My solutions:
A: I tried to put into a block the test_b.html and integrate in the base.html
1, base.html (test1):
{% block conent%}
{% endblock %}
{% block chart%}
{% endblock %}
1, test_b.html (test1):
{% extends "monitor/base.html" %}
{%block chart%}
{%for i in a%}
<p> {{i}}</p>
{%endfor}
{%endblock%}
B: I tried to use {{ block.super }}
1, base.html (test1):
{% block conent%}
{% endblock %}
1, test_b.html (test1):
{% extends "monitor/base.html" %}
{%block content%}
{{ block.super }}
{%for i in a%}
<p> {{i}}</p>
{%endfor}
{%endblock%}
C: Finally I used include method too but I didn't work for me as well. Here I tried to use simple html tags like (<p>Hello world</p>) int the test_b.html and worked. So If I do not use variables it works but I have to use my variables from my views.
1, test_a.html
{% extends "monitor/base.html" %}
{%block chart%}
{%for i in a%}
<p> {{i}}</p>
{%endfor}
{%endblock%}
{% include "my_project/test_b.html" %}
2, test_b.html
{%for i in a%}
<p> {{i}}</p>
{% endfor %}
To include an HTML file from another file just use {% include 'htmlfilename.hml' %}
outside {% block your_block_name %}{% endblock %} if it's a base template.
You can learn more about it here.
<body>
{% include 'header.html' %}
{% block sidebar %}{% endblock %}
{% block content%}{% endblock %}
{% include 'footer.html' %}
</body>
If you want to use some functionality across several templates then use inclusion_tags.
As #alessioferri20 mentioned, you cannot render 2 views at the same time. Basically, one view corresponds to one HTTP request & response.
You can achieve what you want by using custom template tags:
https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/
but I have to use my variables from my views.
For example, chart_data could be an inclusion tag (https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#inclusion-tags), here is some pseudo-code:
Let's say you want to show a chart for the age_stats from your view:
def your_view(request, ...):
age_stats = {...}
....
return render(request, "template...", {'age_stats': age_stats})
In your template:
{% chart age_stats %}
In your template tags:
#register.inclusion_tag('path-to/chart.html')
def chart(input_data):
# collect data from database & use the input_data coming from your view
data = ...
return {'data': data}
The {% include %} tag is how you insert other templates into blocks. These templates don't need to be registered in views.py or urls.py.
For example:
{% extends 'base.html' %} {% block home %} {% load static %}
<div>
<h1>Some Title</h1>
<p>Some text</p>
</div>
<div>
{% include 'some-other-template.html' %}
</div>
{% endblock %}
For more information: https://docs.djangoproject.com/en/4.1/ref/templates/builtins/

Django child template not including content in template tags from base.html

I have a problem in inheriting template from base.html for my about page (about.html). Meanwhile, I am able to extend base.html to home.html. I suspect it is an issue of syntax somewhere either in base.html or about.html, but could not possibly find it. It might also be base.html is only inherited by home.html. Can you please help?
My base. html:
<!DOCTYPE html>
{% load staticfiles %}
<html lang="en">
<head>
<title> {% block title %}{% endblock %} </title>
<h1> {% block h1 %}{% endblock %} </h1>
</head>
<body>
{% block content %}
{% endblock %}
{% block two %}
{% endblock %}
</body>
<!DOCTYPE html>
My about.html:
{% extends "base.html" %}
{% load staticfiles %}
<html lang="en">
<head>
{% block title %}About{% endblock %}
{% block h1 %}Hi,About!{% endblock %}
</head>
<body>
</body>
</html>
Part of my views.py:
from django.shortcuts import get_object_or_404, render_to_response
from ecomstore.catalog.models import Category, Product
from django.template import RequestContext
def about(request, template_name="about.html"):
page_title='About'
return render_to_response(template_name, locals(),RequestContext(request))
My urls.py:
from django.conf.urls import url
from . import views as catalog_views
urlpatterns = [
url(r'$',catalog_views.home,name='home'),
url(r'^about/$',catalog_views.about,name='about'),
In your about.html template you need to add
{% block content %}
<!-- Add your about content here -->
{% endblock content %}
You also don't need <html>, <head> or <body> tags in the about.html file as they are in the base.html file already
When you extend base.html your base.html defines entire html page. In your about.html you just need to code what you want to insert in base.html blocks. So, your about.html have to like this
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}
About
{% endblock %}
{% block h1 %}
Hi,About!
{% endblock %}
I think you want you about.html to look like this.
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}About{% endblock %}
{% block content %}Hi,About!{% endblock %}
Note: You have an <h1> in your header and I think you actually want that in your <body>

Linking CSS & bootstrap in Flask

I've created a flask application and want to link Bootstrap and a custom css file.
What's currently happening is that bootstrap is being applied, but my custom styles in styles.css aren't showing. I know that my file references are correct, because the bootstrap and custom css work independent of one another. How can I get them both to apply at the same time such that I can override the bootstrap defaults in my css?
My template.html looks like this:
{% extends "bootstrap/template.html" %}
{% block head %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="/static/css/styles.css" >
{% endblock %}
{% block title %} -- TITLE -- {% endblock %}
{% block navbar %}
-- NAVBAR HTML --
{% endblock %}
{% block content %}
-- BODY TEXT HTML--
{% endblock %}
A content page looks like this:
{% extends "template.html" %}
{% block title %} -- TITLE -- {% endblock %}
<head>
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
{% endblock %}
</head>
{% block page_content %} PAGE CONTENT
{% endblock %}