路由
Flask路由规则都是基于Werkzeug的路由模块的,它还提供了很多强大的功能。
带参数的路由
一个函数上可以配置多个URL路由规则,如下:
from flask import Flask
from flask import render_template
@app.route('/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
这个例子接受两种URL规则,/不带参数,函数参数name值将为空,页面只显示”Hello World”;/hello/带参数,渲染模版页面会显示参数name的值。
还可以在URL参数前添加转换器来转换参数类型,我们再来加个函数:
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return f'Post {post_id}'
参数类型转换器int:控制好了传入参数的类型只能是整型。目前支持的参数类型转换器有:
类型转换器 | 作用 | |
---|---|---|
缺省 | 字符型,但不能有斜杠 | |
int | 整型 | |
float | 浮点型 | |
path | 字符型,可有斜杠 |
HTTP请求方法设置
HTTP请求方法常用的有Get, Post, Put, Delete。Flask路由规则也可以设置请求方法。
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return 'This is a POST request'
else:
return 'This is a GET request'
URL构建方法
Flask提供了url_for()
方法来快速获取及构建URL,方法的第一个参数指向函数名(加过@app.route
注解的函数),后续的参数对应于要构建的URL变量。
下面是几个例子:
url_for('login') # 返回/login
url_for('login', id='1') # 将id作为URL参数,返回/login?id=1
url_for('hello', name='man') # 适配hello函数的name参数,返回/hello/man
url_for('static', filename='style.css') # 静态文件地址,返回/static/style.css
静态文件位置
一个Web应用的静态文件包括了JS, CSS, 图片等,Flask的风格是将所有静态文件放在”static”子目录下。并且在代码或模板中,使用url_for('static')
来获取静态文件目录。上小节中第四个的例子就是通过url_for()
函数获取”static”目录下的指定文件。如果你想改变这个静态目录的位置,你可以在创建应用时,指定static_folder
参数。
app = Flask(**name**, static_folder='files')
模版
<!doctype html>
<title>Hello Sample</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
它就是一个HTML模板,根据name变量的值,显示不同的内容。变量或表达式由{{ }}修饰,而控制语句由{% %}修饰,其他的代码,就是我们常见的HTML。
模板继承
一般我们的网站虽然页面多,但是很多部分是重用的,比如页首,页脚,导航栏之类的。对于每个页面,都要写这些代码,很麻烦。Flask的Jinja2模板支持模板继承功能,省去了这些重复代码。让我们基于上面的例子,在”templates”目录下,创建一个名为”layout.html”的模板:
<!doctype html>
<title>Hello Sample</title><link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}"><div class="page">
{% block body %}
{% endblock %}
</div>
再修改之前的”hello.html”,把原来的代码定义在{% block body %}
中,并在代码一开始”继承”上面的”layout.html”:
{% extends "layout.html" %}
{% block body %}
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
{% endblock %}
HTML自动转义
我们看下下面的代码:
@app.route('/')
def index():
return '<div>Hello %s</div>' % '<em>Flask</em>'
打开页面,你会看到”Hello Flask”字样,而且”Flask”是斜体的,因为我们加了<em>
标签。但有时我们并不想让这些HTML标签自动转义,特别是传递表单参数时,很容易导致HTML注入的漏洞。我们把上面的代码改下,引入”Markup”类:
from flask import Flask, Markup
app = Flask(__name__)
@app.route('/')
def index():
return Markup('<div>Hello %s</div>') % '<em>Flask</em>'
再次打开页面,标签显示在页面上了。Markup还有很多方法,比如escape()呈现HTML标签, striptags()去除HTML标签。这里就不一一列举了。