In Part 2 we will setup Sanic to render html templates.
Install and setup Jinja2 extension
We will enable our application to render Jinja2 templates. Jinja2 is a template engine developed by Armin Ronacher (the developer of Flask and many other things) and documentation for the project can be found here: https://palletsprojects.com/p/jinja/.
In order to render templates in Sanic we need to first install an extension. Head over to https://github.com/mekicha/awesome-sanic
and find sanic-jinja2
(not jinja2-sanic, which hasn't be updated for some time). The direct link is: https://github.com/lixxu/sanic-jinja2.
Install into your virtualenv
$ pip install sanic-jinja2
In order to enable this extension we need to tell Sanic so. Update our application to
from sanic import Sanic
from sanic import response
from sanic_jinja2 import SanicJinja2
app = Sanic(name='Sanic Web Tutorial')
jinja = SanicJinja2(app, pkg_name="main")
@app.route("/")
async def index(request):
return response.html("<h1>Hello World</h1>")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)
Note that we also add the debut=True
to the app.run() method. This will auto-restart the development server when we
make code changes and provide more debugging info.
Additionally, notice that we set 'pkg_name="main"' when instantiating the jinja object? If you don't do this, you will likely get an error when running main.py. This seems to be a bug in the sanic-jinja2 extension though.
Our first html template
First, create a folder to hold all the templates:
$ mkdir templates
The name is important for now ('templates'). Inside this folder, crate an index.html page:
$ touch templates/index.html
And inside this index.html file, create a boilerplate HTML page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Sanic Web Tutorial</title>
</head>
<body>
<h1>Sanic Web Tutorial</h1>
</body>
</html>
and update our /
route render this template instead of the plain text:
@app.route("/")
async def index(request):
return jinja.render("index.html", request)
You should now be able to see our updated website on: http://0.0.0.0:8000/
Pass variables to the template
Lets say we wan't to pass our title as a parameter in the Python code to the template, how would we do that? Well, the jinja.render() method actually takes 3 arguments, the 3rd being the variables to pass. Lets update to:
@app.route("/")
async def index(request):
return jinja.render("index.html", request, title="Sanic Web Title")
and update the template's h1 tag to be:
<h1>{{ title }}</h1>
The {{ }} brackets is a Jinja2 template tag and it used as a standin for variables passed to the template.
Refresh your webpage on: http://0.0.0.0:8000/ and you should see the updated title.
What if you want to pass multiple variables to the template? Well, we can add multiple variables in the jinja.render function, like this:
@app.route("/")
async def index(request):
return jinja.render("index.html", request, title="Sanic Web Title", desc="Something here")
and update the template's h1 tag to be:
<h1>{{ title }}</h1>
<p>{{ desc }}</p>
This can get quite ugly to read if you have to pass many variables, so we can pass an object instead:
@app.route("/")
async def index(request):
context = {
"title": "Sanic Web Title",
"desc": "Something else here",
}
return jinja.render("index.html", request, context=context)
and we also need to update the html template to account for this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Sanic Web Tutorial</title>
</head>
<body>
<h1>{{ context.title }}</h1>
<p>{{ context.desc }}</p>
</body>
</html>
and if you reload/refresh your website again, you should see that it still shows correctly.