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_pageto return a template. Replace that line and instead, typereturn render_templateand pressAlt-Enter.Select
import this nameand 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
templatesfolder and selectNew -> File. Give it a name ofindex.htmland clickOK.Let’s use Emmet as a way to type fast. In the empty file, type
html>head>titleand presstab. PyCharm will generate much of the markup, leaving your cursor in the<title>.In the
<title>, typeTodo App: {{ title }}and pressShift-Enterto start a new line.Type
body>h1and presstab. Inside the generated<h1>, enter{{ title }}and pressShift-Enter.Type
aand press tab. With the red box in thehref, enter/todo/and pressenter. The cursor moves inside the<a>. TypeTodos.Close the
index.htmltab.In
app.py, note that theindex.htmlis no longer a warning. Confirm that PyCharm can find the template by clicking in'index.html'and pressingCtrl-B. PyCharm opensindex.htmlfrom thetemplatesfolder. (macOS:Cmd-B)Reload your browser on the root URL.
Your
app.pyshould match the following:app.py in Templates¶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.htmlshould match the following:templates/index.html in Templates¶<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.htmlshould be, then was, in a folder calledtemplates? - Besides HTML, where else can you use Emmet in PyCharm?
- Previous topic: Templating
- Next topic: Master Template