Use multiple block and views in django templates - html

I am new to django, and I see that you could create templates that you could populate in views.
You could also create some basic.htm that everyone extends...
Let say I have two pages: (django demo)
List of all questions
Detail of the question.
Now I would like to create "one page" that have first view as sidebar and another as a "detail- right" view.
I would like that on clicking on the list in sidebar change right vies.
It would be nice, if I could use different views (inside views.py) for loading separate templates.
I wish for base html would be something like this :
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Makro Zadravec</title>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'demo/css/bootstrap.min.css.css' %}" />
</head>
<body class="body" style="background-color: #f6f6f6">
<div>
<h1> This is title</h1>
</div>
<div>
{% block sidebar %}
{% endblock %}
</div>
<div>
{% block content %}
{% endblock %}
</div>
</body>
</html>
And then I would have template for blocks:
content
sidebar
in separate views.

Apart from styling here is the logic you can follow this
as you said you already have template which already loaded list of question then your base view would return all the question object as queryset.
First of all, you don't need to write separate template because you can handle this
{% block content %}
// this will load list of all question
{% endblock %}
{% block detail %}
// here display detail of question
{% endblock %}
create two urls to hit one without kwargs and other with kwargs (if you use django version < 2.0 you need to use url instead of path)
path('target/', QuestionView.as_view(), name='target-list'),
path('target/<int:pk>', QuestionView.as_view(), name='target-detail')
Now in view file you just need to handle the kwargs:
class QuestionView(TemplateView):
template_name = "template.html"
model = Question
def get_context_data(self, **kwargs):
context = super(QuestionView, self).get_context_data(**kwargs)
context['question_list'] = #your queryset to list question#
pk = kwargs.get('pk', None) # this will return pk (id of question) if hit url otherwise None
if pk:
context['question_detail'] = #your queryset to get question-detial#
return context
so if you hit url with kwargs it will return both list of question and detail with it as context in template which you can access as below:
{% block content %}
# access question_list to list out all question
{% endblock %}
{% block detial %}
{% if question_detail %} // if question_detail context passed from view
# add detail of question by accessing question_detail
{% endif %}
{% endblock %}

You can do this based on one view.
Create variable called 'question' in your view which at start is defined as an empty string. Then if someone click on some question on sidebar block you can make url with parameter with id of question to show details ('/page/?question=1') or you can store this id in session, as you want. And call same view another time. Then in view you check if you get parameter in url or if it's stored in session and if it's true you assign question object (which you get by id) to variable 'question'. Send this variable to template. In template you render sidebar always and check if variable 'question' is not equal to empty string then you render details for question.
Something like this:
{% block sidebar %}
...
{% endblock %}
{% if question != '' %}
{% block content %}
...
{% enblock %}
{% endif %}

Related

Django template extension; django.template.exceptions.TemplateSyntaxError: Invalid block tag when trying to load i18n from a base template

I have a base.html template file for Django (4.1.2) as:
<!DOCTYPE html>
<html lang="en">
{% load static %}
{% load i18n %}
<head>
<meta charset="utf-8">
{% block title %}
<title>My Title</title>
{% endblock %}
</head>
<body>
{% block content %}
{% endblock content %}
</body>
</html>
and an index.html page, at the same level in the /templates folder of my app, extending the base one, as:
{% extends "base.html" %}
{% block content %}
<h1>My Django project</h1>
<ul>
<li>{% trans "Admin" %}</li>
<li>{% trans "Foo" %}</li>
</ul>
{% endblock %}
But when I browse the latter page, the server returns the following error:
django.template.exceptions.TemplateSyntaxError:
Invalid block tag on line 6:
'trans', expected 'endblock'.
Did you forget to register or load this tag?
But if I simply add {% load i18n %} at the second line of the index.html, the page loads fine.
What is wrong with the loading of the base template in the index.html page?
This doesn't help as it doesn't differentiate the behaviour encountered here with the fact that loading, e.g. {% load django_bootstrap5 %} in base.html is working very well through all child pages without having to ever specify it again in those pages.
you must always load any tag library in each page if you want to use it.Even if the you have already load it in parent page.
I found a way to globally enable i18n in settings.py:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
# ... some options here ...
},
'builtins': ['django.templatetags.i18n'], # <---- add this line
},
]
Then, apparently, you no more need to load this template tag in every html template. It is not even necessary in base.html anymore.
More on templates built-in backends: https://docs.djangoproject.com/en/4.1/topics/templates/#module-django.template.backends.django
And on writing {% load i18n %} only once: https://code.djangoproject.com/ticket/1193
Inspired by: Load a Django template tag library for all views by default

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 %}

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

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.

Django pass variable into template

Hi thank you for helping, I'm poor in coding.
To point: I'm doing a Django project that pass data form data-base to front-end; but right now i can't even pass anything views of Django into templates, I suspect i'm passing the wrong variable types; please do comment on your thought.
This is my code on views.py:
from django.shortcuts import render
def index (requset):
return render(requset,'myapp/index.html') # link to be able open frountend
def testdex(requset):
text = "hello world"
context ={'mytext' : text }
return render(requset,'myapp/inculdes.html', context)
so my variable will be pass into inculdes where extend to index page
This my codes on in inculdes.html:
{% exntends "myapp/index.html" %}
{% block includes %}
{{ mytext }}
{% endblock includes %}
this my code on index.html:
<body>
{% block includes %} {% endblock includes %}
</body>
Thanks again on giving me your time to help me and appreciate it if could write me some code because try fix this for whole week
You can try something like this:
views.py
from django.template.response import TemplateResponse
def testdex(request, template_name="myapp/includes.html"):
args = {}
text = "hello world"
args['mytext'] = text
return TemplateResponse(request, template_name, args)
includes.html
{% extends "myapp/index.html" %}
{% block includes %}
{{ mytext }}
{% endblock includes %}
And make sure you have set path for templates in settings.py
When you do {% block content %}{% endblock content %} you are telling Django that you want to be able to overwrite this section. Please note the word content can be anything to reflect what you want to overwrite.
When you do {{ variable }} you are telling Django that you want to pass a Context. In this example, variable I want to pass is called Title as the key and Portfolio as the value. Context is a dictionary that you pass in views.py like this:
def portfolio_home(request):
return render(request, 'portfolio/work.html', {'title': 'Portfolio'})
Let's say I want to pass a context (or a variable) into my base template. In this example, I want to pass title in the title tag of the head section of my base template.
In the html file for base.html, you need to have something like this:
<!DOCTYPE html>
<html lang="en">
{% load staticfiles %}
<head>
<title>{{ title }}</title>
...........
</head>
</html>
In the urls.py of my project and other apps that I want to pass a title into this, I should create the view like this:
def portfolio_home(request):
return render(request, 'portfolio/work.html', {'title': 'Portfolio'})
I found out why Django can't pass variables to HTML because;
I didn't have my apps url activated the function/model in views
I feel so embarrasses, for such simple mistakes.
All I need to do is add this code in my apps url
urlpatterns = [
path('', views.timedex, name='timedex'), #need add this
path('', views.index, name='index'),
]
Add {{block.super}} before {% endblock includes %}

Flask, jinja2 - Dynamically append templates one after another

I am building a chatbot. There are few child templates like login.html, messages.html, transaction.html, etc. I want to append these templates in base.html dynamically. I am extending base.html in all these templates. My problem is only one template is rendered at a time. Is there any solution for appending these templates one after another? I have used {%include%} but it's a static approach. I need dynamic.
printer.py looks like -
#app.route('/respond', methods=['GET','POST'])
def respond_def():
message = request.form['message_input']
if message == "l":
return render_template('printer/login.html')
elif message == "t":
return render_template('printer/transactionID.html')
base.html looks like -
//some code here
<li>
{% block template %}{% endblock %}
</li>
//some code here
message.html looks like -
{% extends "base.html" %}
{% block template %}
<div> Message template called </div>
{% endblock %}
I resolved it.
I made a list of templates in printer.py and then appended those templates in base.html whenever user asked for it.
printer.py
dictionary = []
// append name of template in this whenever needed.
return render_template('printer/base.html', dictionary=dictionary)
base.html
{% for d in dicts %}
{% set template = 'printer/' + d + '.html' %}
// can add conditions for different templates
{% include template %}
{% endfor %}