Templates¶
Generating HTML from Python can be tiresome. Let’s put Jinja2 templates to work in Flask, while showing some PyCharm features such as Emmet for code completion. For now, though, we’ll just convert one view, the home page, to use a template.
Steps¶
In
app.py
, let’s change the return value ofhome_page
to return a template. Replace that line and instead, typereturn render_template
and pressAlt-Enter
.Select
import this name
and select the first choice, fromflask
.Finish typing that line, resulting in:
@app.route('/') def home_page(): return render_template('index.html', title='Home Page')
PyCharm warns us that
Template file 'index.html' not found
. Let’s create it.Right-click in the Project Tool window on the
templates
folder and selectNew -> File
. Give it a name ofindex.html
and clickOK
.Let’s use Emmet as a way to type fast. In the empty file, type
html>head>title
and presstab
. PyCharm will generate much of the markup, leaving your cursor in the<title>
.In the
<title>
, typeTodo App: {{ title }}
and pressShift-Enter
to start a new line.Type
body>h1
and presstab
. Inside the generated<h1>
, enter{{ title }}
and pressShift-Enter
.Type
a
and press tab. With the red box in thehref
, enter/todo/
and pressenter
. The cursor moves inside the<a>
. TypeTodos
.Close the
index.html
tab.In
app.py
, note that theindex.html
is no longer a warning. Confirm that PyCharm can find the template by clicking in'index.html'
and pressingCtrl-B
. PyCharm opensindex.html
from thetemplates
folder. (macOS:Cmd-B
)Reload your browser on the root URL.
Your
app.py
should match the following:from flask import Flask from flask import render_template from models import populate_todos, Todo app = Flask(__name__) @app.route('/') def home_page(): return render_template('index.html', title='Home Page') @app.route('/todo/') def list_todos(): todos = Todo.list() div = '<div><a href="/todo/{id}">{title}</a></div>' items = [div.format(id=t.id, title=t.title) for t in todos] return '\n'.join(items) @app.route('/todo/<int:todo_id>') def show_todo(todo_id): todo = Todo.get_id(todo_id) fmt = '<h1>Todo {todo_id}</h1><p>{title}</p>' return fmt.format(todo_id=todo.id, title=todo.title) if __name__ == '__main__': populate_todos() app.run(debug=True)
Your
templates/index.html
should match the following:<html> <head><title>Todo App: {{ title }}</title></head> <body> <h1>{{ title }}</h1> <a href="/todo/">Todos</a> </body> </html>
Analysis¶
We added Flask template support, but saw a few last productivity features along the way:
- Emmet support. PyCharm has a number of facilities for generating code. We previously saw Live Templates. Emmet is another. Postfix completion is a third way.
- Templates directory. PyCharm warned us that a file didn’t exist in the Flask templates directory.
Extra Credit¶
- How did PyCharm know that
index.html
should be, then was, in a folder calledtemplates
? - Besides HTML, where else can you use Emmet in PyCharm?
- Previous topic: Templating
- Next topic: Master Template