How to pass multiple templates to flask.render_template() - python

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()

Related

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.

Having problems with the usage of a block in Flask

so I tried bulding a (small) website (for learning purposes) and had a few problems with the usage of a block.
I have the feeling that the problem is something obvious, but I can't figure it out.
Here is my code:
# main.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def home():
return render_template("main.html")
if __name__ == "__main__":
app.run(debug=True)
# main.html
<!DOCTYPE html>
<head>
<title>
{% block title %}{% endblock %}
</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
# mainexdended.html
{% extends "main.html" %}
{% block title %}Test{% endblock %}
{% block content %}
<h1> Content Test </h1>
{% endblock %}
Now, when I run the code, I just get a blank page. Everything defined in the mainextended.html gets ignored.
How can I change that?
That's because you are rendering main.html, not mainextended.html.
You need to change
#app.route("/")
def home():
return render_template("mainextended.html")
Than you should see the contents of both, main.html and mainextended.html
If you use "extend" you always want to render the "extending" html, there is also a function to include content tho, which would work the other way round.

How to pass variable into a string? Jinja2

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)

While using flask in python, I am not able to get the 'extend' feature to work properly

I'm new to programming. I decided to try to create a web app using flask, python, and HTML. I set up three files; two HTML and one python:
This is the HTML file that should have information replaced (didntwork.html):
<!doctype html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h3>Information:</h3>
{% block body %}{% endblock %}
</body>
</html>
.
This is the file that should input information to the first (connection.html):
{% extends 'didntwork.html' %}
{% block body %}
<h4>information content</h4>
{% endblock %}
.
Finally, this is the logic for the flask app in python (main.py):
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('didntwork.html')
if __name__ == '__main__':
app.run(debug=True)
Unfortunately, the extends in the second HTML file does not seem to be recognized, and the information in its block will not be replaced in the first HTML file (didntwork.html).
This is the output:
The expected outcome should append an h4 tag to the body with the phrase 'information content'.
Any help would be appreciated, thanks.
The problem is the {% extends 'didntwork.html' %}. From what I can tell the file that contains this code:
<!doctype html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h3>Information:</h3>
{% block body %}{% endblock %}
</body>
</html>
is your connection.html file.
You are extending to the same file you're rendering (didntwork.html). You have to change the extends line to extend your base html, connection.html in this case.
Use this code in your didntwork.html:
{% extends 'connection.html' %}
{% block body %}
<h4>information content</h4>
{% endblock %}
You can find more information in Template Inheritance
UPDATE BASE ON CLARIFICATION
You're rendering the wrong file in your route.
You should render the connection.html and this will extends your didntwork.html file.

Running python script using html in Flask

I'm new to Flask and I'm trying to run a python script from background upon click on a button in a html page. Here is my code:
from flask import *
from functools import wraps
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
#app.route('/generate')
def generate():
return render_template('process.html')
and my process.html is as follows:
<html>
<head>
<body>
Processing...
<script>
exec('python /pth to my python file/myfile.py')
</script>
</body>
</head>
</html>
and home.html is as follows:
{% extends "template.html" %}
{% block content %}
<div class = "jumbo">
<h2> Home</h2>
<br/>
<p>click me</p>
<p> lorem epsum </p>
<div>
{% endblock %}
I'm working on linux and I do not know whether it is possible to use exec in html as shown above. However exec command inside .html file is not executing. I'm still new to flask and I would appreaciate any suggestion on how to make it work.
The <script> tag in HTML is specifically for running client-side JavaScript code. Back-end logic should be done in the views. If you're just looking to execute a line of code that is present in myfile.py, you should put it in a function in that file and import it using from myfile import functionname or simply have that code present in the views (the latter being the proper way to do it in most cases). For example, if myfile.py contained print 'Hello World!' then your views should look like this:
from flask import *
from functools import wraps
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
#app.route('/generate')
def generate():
print 'Hello World!'
return render_template('process.html')
If you did it this way, you wouldn't have to split all of your code up into separate files. Unfortunately though, the template would be rendered after the code is executed, so 'Processing...' as shown in your process.html template would display after it has already been processed. As far as Flask goes, the best way that I'm aware of to show the user that the process took place would be to redirect back to the page and flash a message, like this:
#app.route('/generate')
def generate():
print 'Hello World!'
flash('Process complete!')
return redirect(url_for(home))
and then in home.html you would have something like this (from Flask 0.11 Documentation):
{% extends "template.html" %}
{% block content %}
<div class = "jumbo">
<h2> Home</h2>
<br/>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<p>click me</p>
<p> lorem epsum </p>
<div>
{% endblock %}
If you wanted something like 'Processing...' to display on the page, that's when you would want to use JavaScript.
Hopefully this helps :)

Categories

Resources