1.Jinja2
视图函数返回的一般都是字符串,但在实际的网站中,为了让网页更加美观,需要对页面进行文本标签渲染,通常包含大量的HTML代码,如果将这些HTML代码通过字符串的形式写在视图函数中,复杂程度会加剧。因此,在Flask中,渲染视图函数一般通过模板引擎来完成,而Flask中默认的模板引擎就是Jinja2,Jinja2可以独立于Flask使用。
2.模板基本使用
使用Pycharm创建完成一个Flask项目后,默认会生成一个templates文件夹,默认在templates这个文件夹内寻找模板文件。模板文件可以是任意纯文本格式的文件,但是为了让项目更规范,一般使用HTML文件来写模板代码。如果项目中没有自动生成templates文件夹,可以手动创建一个。
# app.py文件 from flask import Flask from flask import render_template app = Flask(__name__) @app.route('/') def index(): # 会在项目根路径下的templates下寻找index.html文件 return render_template("index.html") if __name__ == '__main__': app.run()
# HTML模板 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Flask模板文件</title> </head> <body> <h1>我是由Jinja2模板引擎渲染的!</h1> </body> </html>
3.渲染变量
在HTML文件中,有些数据是需要在数据库中动态加载的。比如博客列表需要读取最新的博客数据。
# app.py文件 from flask import Flask,render_template app = Flask(__name__) @app.route('/variable') def variable(): # put application's code here hobby="看剧" return render_template("variable.html",hobby=hobby) if __name__ == '__main__': app.run()HTML文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>变量使用</title> </head> <body> <div>我的兴趣爱好是:{{ hobby }}</div> </body> </html>
如在上述代码中,使用了{{ 变量名称 }}的语法,来读取视图函数中传递过来的变量hobby。
在模板中,可以使用对象.属性或字典.key的语法来访问对应的值。比如下述的代码:
# app.py文件 from flask import Flask,render_template app = Flask(__name__) class User: def __init__(self,username,email): self.username = username self.email = email @app.route('/variable') def variable(): # put application's code here hobby="看剧" person={ "name":"张三", "age":18, } user=User(username='李四',email='12345@qq.com') # 字典 context={ "hobby":hobby, "person":person, "user":user, } # return render_template("variable.html",hobby=hobby,person=person,user=user) render_template('variable.html',**context) if __name__ == '__main__': app.run()HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>变量使用</title> </head> <body> <div>我的兴趣爱好是:{{ hobby }}</div> <div>person的名字是:{{ person['name'] }},person的年龄是:{{ person.age }}</div> <div>user的名字是:{{ user.username }},user的Email是:{{ user.email }}</div> </body> </html>
4.控制语句
在模板中,也存在if和for等控制语句,但所有的控制语句都放在{% %}当中,并且控制语句结束之后需要加入相应的结束语句。
if语句
Jinja2中if语句可以通过>、<、!=、==、>=、<=来判断,也可以通过and、or、not来进行逻辑操作。
# app.py文件 from flask import Flask,render_template app = Flask(__name__) # if 语句 @app.route('/if') def if_statement(): age=18 return render_template("if.html",age=age) if __name__ == '__main__': app.run()
# HTML文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>if控制语句</title> </head> <body> {% if age > 18 %} <div>你已成年!</div> {% elif age < 18 %} <div>你未成年!</div> {% else %} <div>你刚好成年!</div> {% endif %} </body> </html>
注意:if语句中必须跟一个结束语句endif;在模板中缩进并不是必要的;{和%必须紧跟。
for语句
Jinja2中的for循环与python中的for循环相似,只是比python在多一个endfor语句。
# app.py文件 from flask import Flask,render_template app = Flask(__name__) @app.route('/for') def for_statement(): books=[{ "name":"三国演义", "author":"罗贯中", "price":100 },{ "name": "水浒传", "author": "施耐庵", "price": 90 },{ "name": "红楼梦", "author": "曹雪芹", "price": 120 },{ "name": "西游记", "author": "吴承恩", "price": 105 }] return render_template("for.html",books=books) if __name__ == '__main__': app.run()HTML文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>for语句</title> </head> <body> <table> <thead> <tr> <tr>书名<tr> <tr>作者<tr> <tr>价格<tr> </tr> </thead> <tbody> {% for book in books %} <tr> <td>{{ book.name }}</td> <td>{{ book.author }}</td> <td>{{ book.price }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
注意:Jinja2中没有break和continue语句。
5.模板继承
一个网站中,大部分网页的模板都是重复的(例如,网页的顶部和底部),如果在每个页面都重复的去写这些代码,会让项目变得臃肿,提高成本。因此,可以提高模板继承把一些重复的代码写在父模板中,子模版继承父模板后,再分别实现不同页面的代码。
# 父类代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %} | 果壳 科技有意思</title> {% block head %}{% endblock %} </head> <body> <nav> <ul> <li><a href="#">首页</a></li> <li><a href="#">发布</a></li> </ul> </nav> <main> {% block main %}{% endblock %} </main> <footer> Copyright 2008 by <a href="http//domain.invalid">you</a> </footer> </body> </html>
在父类代码中,编写好了网页的整体结构,然后针对子模版需要重写的地方,则定义成block。子模版在继承了父模板后,重写对应的block代码,即可完成子模版的渲染。
# 子模版 {% extends "base/base.html" %} {% block title %}列表页{% endblock %} {% block head %} <style> body{ background: antiquewhite; } </style> {% endblock %} {% block main %} <h1>这是果壳文章列表页!</h1> {% endblock %}
注意:通过extends语法,加载父模板,extends必须出现在子模版所有的代码最前面。
6.静态文件的架加载
一个网页,除了HTML外,还需要CSS、Javascript和图片文件才能更加美观,静态文件是默认存储在当前项目的static文件夹中,在模板文件中,可以通过url_for加载静态文件。
# app.py文件 from flask import Flask,render_template app = Flask(__name__) @app.route("/template/static") def template_static(): return render_template("static.html") if __name__ == '__main__': app.run()
# HTML文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="{{ url_for('static',filename='CSS/mystatic.css') }}"> {# <link rel="stylesheet" href="/static/CSS/mystatic.css">#} <title>静态文件加载</title> </head> <body> <h1 class="title">静态文件加载</h1> </body> </html>
# mystatic.css .title{ background: brown; }