How to pass variable into a string? Jinja2 - python

How do I pass in a variable into a template in Jinja2?
I can normally do it like
<p>Hello, {{ var }}</p>
And then in python do:
#app.route('/hello')
def hello():
return render_template('hello.html', var = "World")
Which will result in:
Hello, World
But, let's say I want a custom bg-color for every page.
If I try
<body bgcolor="{{ bg_color }}">
</body>
and in python do:
#app.route('/hello')
def hello():
return render_template('hello.html', bg_color = "black")
It doesn't work! Can anyone help?

use jinja2 template inheritance
in your base template you need to add block like
base.html
[..]
<body{% block body_attributes %}{% endblock %}>
[..]
and then in child templates you extend base.html template like:
page1.html
{% extends "base.html" %}
{% block body_attributes %}class="bg-red"{% endblock %}
[..]
page2.html
{% extends "base.html" %}
{% block body_attributes %}class="bg-blue"{% endblock %}
[..]
you can add other attributes (id, data-spy="scroll" data-target="#navbar-example3" data-offset="0" if you are using the bootstrap scrollspy ... ) for the body tag depending on the page

I don't think you can bind class like that. Here is an example of conditional class binding if its useful in your case.
<div class="{% if black_backgroud %} black {% endif %}">...</div>
and in python
#app.route('/hello')
def hello():
return render_template('hello.html', black_backgroud = True)

Related

Return html tag by calling python function in django template

Guys actually i am expecting the django view should return only the tag like
def load_tags():
return httpresponse("<span>span tag</span>")
def home(request):
return render(request, 'index.html',{"func":load_tags()})
html file
<h2>Calling python function {{ func }} </h2>
-In browser it displayed as
Calling python function <HttpResponse status_code=200, "text/html; charset=utf-8">
-But i am expecting as
Calling python function span tag
Guys can you help me to achieve this functionality
I tried to solve your requirement like this...
views.py
def TagsView():
html_h1 = "<h1>Hello django</h1>"
html_italic = "<h4><i>Hello django</i></h4>"
html_hr = "<hr>"
my_code = "<code>print('Hello world')</code>"
return html_h1,html_italic,html_hr,my_code
def DemoView(request):
context = {"func":TagsView()}
return render(request, 'index.html',context)
HTML Code
{% block body %}
{% autoescape off %}
{% for i in func %}
{{i}}
{% endfor %}
{% endautoescape %}
{% endblock body %}
Output

Does flask.render_template() create variables with the None keyword assigned to them?

I have 4 files:
flask_blog.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
#app.route("/home")
def home_page():
return render_template("home.html")
#app.route("/about")
def about():
return render_template("about.html", title = "About")
layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>Flask Blog - {{ title }}</title>
{% else %}
<title>Flask Blog</title>
{% endif %}
</head>
<body>
{% block content %}{% endblock content %}
</body>
</html>
home.html
{% extends "layout.html" %}
{% block content %}{% endblock content %}
about.html
{% extends "layout.html" %}
{% block content %}{% endblock content %}
On my about page, the title is "Flask Blog - About", and in my home page, the title is "Flask blog". Now, this is happening due to the if/else statements in the layout.html file. The if/else statements are:
{% if title %}
<title>Flask Blog - {{ title }}</title>
{% else %}
<title>Flask Blog</title>
{% endif %}
Now, the value of the 'title' variable must be 0 or None, since we are going to the else statement for the home page. Now, my question is, we didn't assign a value to the 'title' variable beforehand. Better yet, we haven't even created the 'title' variable in the flask_blog.py file. How are we not getting a NameError? Shouldn't we get NameError: name 'title' is not defined?
Related
The templating language used by default in flask is Jinja. Jinja is not Python, and as such it works a little differently sometimes.
When a variable is not defined, if statements in Jinja template evaluate to False. As a result it doesn't throw an exception but instead it just goes to the next else block.
More specifically, an undefined variable becomes of type Undefined, which has it's own documentation page: https://jinja.palletsprojects.com/en/3.1.x/api/#undefined-types
This is useful in a templating language, because it makes it easier to re-use complex templates without having to specify every parameter every time you render it. If a parameter (and corresponding if block) is not relevant for a call to render_template, you can just omit it and don't worry about it.

using mongoDB collection in one page twice

Hi2all!
I have:
1) mongo collection:
[{_id:ObjectId("5b0d5fb624d22e1b4843c06b")
collectionName:"collection0"
collectionCaption:"caption1"}
{_id:ObjectId("5b0d5fb824d22e1b4843d4c1")
collectionName:"collection1"
collectionCaption:"caption1"}
{_id:ObjectId("5b0d5fb924d22e1b4843d74a")
collectionName:"collection2"
collectionCaption:"caption1"}
{_id:ObjectId("5b0d5fb924d22e1b4843d7b0")
collectionName:"collection3"
collectionCaption:"caption1"}]
2) flask app with the view:
def index():
a = mongo.db.collectionsNames.find()
return render_template('index.html', collectionsNames=a)
3) templates: index.html witch extend base.html.
base.html:
{% extends "bootstrap/base.html" %}
{% block content %}
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
{% for asd in collectionsNames %}
<a class="dropdown-item" href="/{{ asd["collectionName"] }}">{{ asd["collectionCaption"] }}</a>
{% endfor %}
</div>
{% block contentBase %} {% endblock %}
{% endblock %}
index.html:
{% extends "base.html" %}
{% block contentBase %}
{% for zxc in collectionsNames %}
{{ zxc["collectionName"] }}
{% endfor %}
{% endblock %}
The question is: why if base and index using the same variable of collection, index template show nothing?
But if in view code is:
def index():
a = mongo.db.collectionsNames.find()
b = mongo.db.collectionsNames.find()
return render_template('index.html', collectionsNames1=a, collectionsNames2=b)
and in templates i am using the different variables, the index template show me the data.
mongo.db.collectionsNames.find() returns a cursor: print(mongo.db.collectionsNames.find()) gives <pymongo.cursor.Cursor object at 0x7fd3854d5710>.
To make it easy (but kind of wrong) a cursor is a specific kind of instance that fetch data from the database chunk by chunk so if you want the 1 000 000 first items in db you don't actually store 1M items in RAM, you iterate 100 by 100 items (for example). Cursor handle that in a magic way.
Whatever, you cannot loop several time on the same cursor and you should never caste a cursor to list like list(cursor_instance) (because if your query ask for 1M product, doing this add all these products in RAM).
So, now, how can you handle this. Most of time I would say it's better to call the method when you need it, twice if needed.
But here you are in a Jinja environment and if I'm right calling methods within a Jinja template is impossible.
A way to do that is to use properties.
class LazyCollection(object):
#property
def collections_names(self):
return mongo.db.collectionsNames.find()
lazycoll = LazyCollection()
return render_template('index.html', collectionsNames=lazycoll)
Then, in your template:
{% for asd in collectionsNames.collections_names %}
<p>{{ asd.foo }}</p>
{% endfor %}

How to pass multiple templates to flask.render_template()

I'm trying to deploy a flask app and I want a flask.render_template() method passed with a list of html files. Here I see it's eligible. http://flask.pocoo.org/docs/0.12/api/#flask.render_template
I'm trying with this code
from flask import Flask, render_template
app = Flask(__name__)
app.debug = True
#app.route('/')
def hello():
templs = ["_header.html", "_footer.html"]
return render_template(templs)
if __name__== '__main__':
app.run()
But actually server returns only the first template from the list.
How to iterate though this list in order to render all templates from the list?
Thanks,
Alex
As far as i see you are trying to render static header and footer. I'd recommend to prepare something like "layout.html" with included header and footer:
//layout.html
<html>
<head>//headhere</head>
<header>//your static header</header>
<main>
{% block body %}
//content will be here
{% endblock %}
</main>
<footer> //your static footer </footer>
</html>
then in "child" templates(ex: index.html)use:
//index.html
{% extends "layout.html" %}
{% block body %}
//your code here
{% endblock %}
It will render header and footer from layout.html and rest from index.html.
You probably don't want to render multiple templates. What you want is to render one template that combines multiple templates. That is the task of templating engine, not Flask. See http://jinja.pocoo.org/docs/dev/templates/ (Flask uses Jinja).
Exactly like #jbasko wrote!
Making use of two {{block}} statements worked for me:
For example, I put in my routes.py
#app.route("/page1")
def page1():
return render_template('page1.html', title='Title')
the page1.html is containing simply two block-specifications
{% extends "page1.html" %}
{% block content %}
<h1> Content </h1>
{% endblock content %}
{% block info %}
<h1> Info </h1>
{% endblock info %}
which gets referenced in layout.html in two separate places:
{% block content %}{% endblock %}
and later
{% block info %}{% endblock %}
Thanks for the help everyone!
you can try this...
from flask import Flask, render_template
app = Flask(__name__)
app.debug = True
#app.route('/')
def hello():
render_header = render_template('_header.html')
render_footer = render_template('_footer.html')
return render_header + render_footer
if __name__ == '__main__':
app.run()

Call python function using HTML

I have a function in python that displays a list of names.
def search():
with open('business_ten.json') as f:
data=f.read()
jsondata=json.loads(data)
for row in jsondata['rows']:
#print row['text']
a=str(row['name'])
print a
return a
search()
I am trying to call this function in an HTML file using Flask
{% extends "layout.html" %}
{% block content %}
<div class="jumbo">
<h2>Welcome to the Rating app<h2>
<h3>This is the home page for the Rating app<h3>
</div>
<body>
<p>{{ search.a }}</p>
</body>
{% endblock %}
My routes file is as follows:
from flask import Flask,render_template
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello gugugWorld!'
#app.route('/crawl')
def crawl():
return render_template('crawl.html')
There are many ways to do this:
1 - You can register a new Jinja2 filter
2 - You can pass your function as a Jinja2 parameter (This one is easier)
For method 2:
#app.route('/crawl')
def crawl():
return render_template('crawl.html', myfunction=search)
On the template call the parameter has a function
{% extends "layout.html" %}
{% block content %}
<div class="jumbo">
<h2>Welcome to the Rating app<h2>
<h3>This is the home page for the Rating app<h3>
</div>
<body>
<p>{{ myfunction() }}</p>
</body>
{% endblock %}

Categories

Resources