Why aren't Jinja2 extend statements and block statements not working? - html

This is my base.html
<html>
<head>
{% block head %}
{% endblock %}
</head>
<body>
Outside Block
{% block body %}
{% endblock %}
</body>
</html>
This is my index.html
{% extends 'templates/base.html' %}
{% block body %}
<h1> Inside Block </h1>
{% endblock %}
My endpoint:
#app.route('/')
def home():
return render_template('base.html')
And my browser displays
Outside Block
Whenever I execute my code everything except the blocks are displayed. I can even display a value by passing it as a parameter and display it as {{value}} or use an if condition even include is working. Just the block statements are not working.
What could be the reason for this?

You need to return the index.html instead of base.html
#app.route('/')
def home():
return render_template('index.html')
Also you nee to extend 'base.html' not 'templates/base.html' in your index.html file.

Related

Jinja Scope on Inherited Template

I am developing a website using Flask on the back-end and Jinja for templating. Every page should have the same image as part of the Open Graph Protocol, except for one of them, where I want to customize the url with something peculiar to that page.
The child template (like all other templates) extends base, but only this one will ever have a value set for the variable ob_image_url, therefore I need to check if that value exists and if not set a default value.
When the child page.html template is rendered, I am always getting the default value and not the one for that page. Where am I messing it up?
Thanks!
base.html
{% block og_image %}{% endblock %}
{% if not og_image_url %}
{% set og_image_url = url_for('static', filename='img/logo.png', _external=True) %}
{% endif %}
<meta property="og:image" content="{{og_image_url}}" />
page.html
{% extends "base.html" %}
{% block og_image %}
{% if obj and obj.image %}
{% set og_image_url = obj.image %}
{% endif %}
{% endblock %}

SqlAlchemy query db.session.query() output format into HTML

I am running a db query with sqlalchemy and then pushing this output into an HTML page with flask and python. However, the output is formatted as a list, and I am trying to remove the quotes around it and format it nicer.
# views.py
#buyers_blueprint.route('/welcome')
#login_required
def welcome_user():
user = current_user
events = db.session.query(Events.eventname)
return render_template('welcome.html', user=user, events=events)
The welcome.html page is simple and looks like this
welcome.html
{% extends "base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Events Dashboard</h1>
<p>{{user}}! You are logged in.<br>
Here is a list of your events</p><br>
<p>
{% for event in events %}
<li>{{event}}</li>
{% endfor %}
</p>
</div>
{% endblock %}
The output looks like this.
('Event 1',)
('Event 2',)
How do I remove the quotes, and comma to format it so it looks nicer? Thank you so much.
So, thanks to help from others, I came up with an answer. In the HTML, I just needed to ask for the first in tuple.
welcome.html
{% extends "base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Events Dashboard</h1>
<p>{{user}}! You are logged in.<br>
Here is a list of your events</p><br>
<p>
{% for event in events %}
<li>{{event[0]}}</li>
{% endfor %}
</p>
</div>
{% endblock %}

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>

Template Inheritance in Nunjucks, what are the requirements?

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.