Flask Web开发实战:深入Jinja2模板引擎与表单处理
本文详细讲解如何在Flask应用中集成Jinja2模板引擎,通过分离HTML与Python代码提升可维护性。内容涵盖基础路由、POST请求处理、模板变量传递、常用过滤器、控制语句及宏定义,并深入演示模板继承机制,为后续整合Bootstrap前端框架奠定基础。
完成第一章的基础学习后,我们已经能够构建简单的网页。接下来,我们将利用这一方式创建一个登录页面。首先,需要定义一个处理login路由的方法。
@app.route("/login",methods=["GET"])
def login():
html="<form method='post'>" \
"<table>" \
"<tr><td>请输入用户名</td><td><input type='text' name='username'/></td></tr>" \
"<tr><td>请输入密码</td><td><input type='password' name='password'/></td></tr>" \
"<tr><td><input type='submit' value='登录'/></td></tr>" \
"</table>" \
"</post>"
return html
该页面返回的是一个基础的登录界面,具体显示效果如下所示。

随后,我们需要处理登录提交后的POST请求页面。
@app.route("/login",methods=["POST"])
def loginPost():
username=request.form.get("username","")
password=request.form.get("password","")
if username=="test" and password=="123" :
return "登录成功"
else:
return "登录失败"当输入用户名test和密码123并提交后,页面将显示登录成功。

虽然功能上实现了预期效果,但从实际应用角度来看,这还远未达到可部署程序的标准。即便暂且不考虑JavaScript脚本和CSS样式表的引入,仅从代码维护的角度来看,这也是一场噩梦。例如,若要增加一个验证码输入框,相信没有人会觉得这是一项轻松愉快的工作。
因此,首要任务是分离页面HTML部分。Flask提供了Jinja2模板引擎来实现这一目标。
Jinja2模板引擎遵循Flask的基本约定,即在众多配置项中存在基础默认值。对于Jinja2而言,最重要的默认配置是模板文件应放置在templates文件夹中。尽管该文件夹路径可以自定义,但使用默认值目前足以满足需求。
首先,在PyCharm项目的根目录下创建templates文件夹,并在其中新建login.html文件。此时的目录结构如下所示。

在login.html文件中输入以下代码。
<!DOCTYPE html> <html> <head> <title>欢迎您登陆--牛博客</title> </head> <body> <form method='post'> <table> <tr><td>请输入用户名</td><td><input type='text' name='username'/></td></tr> <tr><td>请输入密码</td><td><input type='password' name='password'/></td></tr> <tr><td><input type='submit' value='登录'/></td></tr> </table> </form> </body> </html>
这段代码非常简单,且未进行任何样式美化。但对我而言,仅仅因为获得了代码智能感知的支持,这就足以成为使用模板的理由。接着,我们需要修改default.py文件中的login方法,代码如下。
from flask import render_template #头部,引入模板渲染方法
@app.route("/login",methods=["GET"])
def login():
return render_template("/login.html")
#渲染模板,默认找templates文件夹下的login.html文件
由于HTML模板内的代码逻辑与直接写在Python文件中的效果一致,此时刷新页面,显示效果与之前完全相同。虽然视觉效果没有显著改善,但如果后续需要修改HTML中的某个元素,操作将变得便捷许多。
关于Jinja2模板引擎,它还支持一些更强大的功能,例如使用index参数进行说明。
以下是其基本用法。
我们需要修改default.py文件中的部分代码,具体如下。
from flask import render_template #页头,导入渲染函数
@app.route("/")
def index():
return render_template("index.html",site_name='myblog')
对应的index.html文件代码如下。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{site_name}}</title>
</head>
<body>
<h1>这个站点的名字为 {{site_name}} </h1>
</body>
</html>
Flask的render_template函数支持多参数传递。函数的第一个参数指定模板名称,后续参数为若干键值对,用于向模板变量提供数据。如本例所示,我们将myblog赋值给site_name,而在模板中通过{{参数名}}的语法表示该变量。
此时在浏览器中输入地址,输出结果如下。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>myblog</title> </head> <body> <h1>这个站点的名字为 myblog </h1> </body> </html>
Jinja2模板还提供了一些变量过滤器,例如以下代码所示。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{site_name|upper}}</title>
</head>
<body>
<h1>这个站点的名字为 {{site_name}} </h1>
</body>
</html>
此时的输出结果为。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>MYBLOG</title> </head> <body> <h1>这个站点的名字为 myblog </h1> </body> </html>
以下是常用的过滤器列表。
safe:不进行转义处理 capitalize:首字母大写 lower:转换为小写 upper:转换为大写 trim:去除首尾空格 striptages:去除HTML标签
此外,Jinja2中的变量还可以是复杂类型,甚至可以使用复杂类型的常用方法,例如。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{site_name[2:]}}</title>
</head>
<body>
<h1>这个站点的名字为 {{site_name}} </h1>
</body>
</html>
此时的输出结果为。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>blog</title> </head> <body> <h1>这个站点的名字为 myblog </h1> </body> </html>
接下来介绍控制语句。
控制语句是模板的基本功能,Jinja2同样提供了相应的支持。
//选择
{% if name=='test' %}
这是测试
{% else %}
{{name}},你好
{% endif %}
//循环
<ul>
{% for blog in blogs%}
{{ blog.title }}
{% endfor%}
</ul>
除了上述基本用法,模板还为代码复用提供了宏功能。例如,将以下代码写入macros.html文件中。
{% macro render_title(blog)%}
<li>{{blog.title}}</li>
{% endmacro%}
然后在之前的模板中引入该宏。
{% import 'macros.html' as macros %}
<ul>
{% for blog in blogs %}
{{ macros.render_title(blog) }}
{% endfor %}
</ul>
执行结果与之前的效果完全相同。
Jinja2还提供了一个更为强大的功能,即模板继承。这让人联想到Java中的Sitemesh框架。它首先需要创建一个base.html基模板。
<!DOCTYPE html>
<html>
<head>
{% block head %}
<meta charset="UTF-8">
<title>{% block title%} {% endblock %} - 牛博客</title>
<script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
其中block标签表示在子模板中可以进行修改。具体到本例,可修改的部分包括head、title和body。以下是子模板的代码。
{% extends "base.html" %}
{% block title %}{{site_name[2:]}}{% endblock %}
{% block head %}
{{super()}}
{% endblock %}
{% block body %}
<h1>这个站点的名字为 {{site_name}} </h1>
{% endblock %}
此时执行结果仍为。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>blog</title> </head> <body> <h1>这个站点的名字为 myblog </h1> </body> </html>
现在拥有了模板引擎,仅从页面层面来说,已经可以相对轻松地实现不少功能。但很明显,当前界面美观度尚显不足。下一章将介绍如何将目前主流的前端框架Bootstrap与Flask框架进行整合。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













