路由

Flask路由规则都是基于Werkzeug的路由模块的,它还提供了很多强大的功能。

带参数的路由

一个函数上可以配置多个URL路由规则,如下:

  1. from flask import Flask
  2. from flask import render_template
  3. @app.route('/')
  4. @app.route('/hello/<name>')
  5. def hello(name=None):
  6. return render_template('hello.html', name=name)

这个例子接受两种URL规则,/不带参数,函数参数name值将为空,页面只显示”Hello World”;/hello/带参数,渲染模版页面会显示参数name的值。

还可以在URL参数前添加转换器来转换参数类型,我们再来加个函数:

  1. @app.route('/post/<int:post_id>')
  2. def show_post(post_id):
  3. # show the post with the given id, the id is an integer
  4. return f'Post {post_id}'

参数类型转换器int:控制好了传入参数的类型只能是整型。目前支持的参数类型转换器有:

类型转换器 作用
缺省 字符型,但不能有斜杠
int 整型
float 浮点型
path 字符型,可有斜杠

HTTP请求方法设置

HTTP请求方法常用的有Get, Post, Put, Delete。Flask路由规则也可以设置请求方法。

  1. from flask import request
  2. @app.route('/login', methods=['GET', 'POST'])
  3. def login():
  4. if request.method == 'POST':
  5. return 'This is a POST request'
  6. else:
  7. return 'This is a GET request'

URL构建方法

Flask提供了url_for()方法来快速获取及构建URL,方法的第一个参数指向函数名(加过@app.route注解的函数),后续的参数对应于要构建的URL变量。

下面是几个例子:

  1. url_for('login') # 返回/login
  2. url_for('login', id='1') # 将id作为URL参数,返回/login?id=1
  3. url_for('hello', name='man') # 适配hello函数的name参数,返回/hello/man
  4. url_for('static', filename='style.css') # 静态文件地址,返回/static/style.css

静态文件位置

一个Web应用的静态文件包括了JS, CSS, 图片等,Flask的风格是将所有静态文件放在”static”子目录下。并且在代码或模板中,使用url_for('static')来获取静态文件目录。上小节中第四个的例子就是通过url_for()函数获取”static”目录下的指定文件。如果你想改变这个静态目录的位置,你可以在创建应用时,指定static_folder参数。

  1. app = Flask(**name**, static_folder='files')

模版

  1. <!doctype html>
  2. <title>Hello Sample</title>
  3. {% if name %}
  4. <h1>Hello {{ name }}!</h1>
  5. {% else %}
  6. <h1>Hello World!</h1>
  7. {% endif %}

它就是一个HTML模板,根据name变量的值,显示不同的内容。变量或表达式由{{ }}修饰,而控制语句由{% %}修饰,其他的代码,就是我们常见的HTML。

模板继承

一般我们的网站虽然页面多,但是很多部分是重用的,比如页首,页脚,导航栏之类的。对于每个页面,都要写这些代码,很麻烦。Flask的Jinja2模板支持模板继承功能,省去了这些重复代码。让我们基于上面的例子,在”templates”目录下,创建一个名为”layout.html”的模板:

  1. <!doctype html>
  2. <title>Hello Sample</title><link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}"><div class="page">
  3. {% block body %}
  4. {% endblock %}
  5. </div>

再修改之前的”hello.html”,把原来的代码定义在{% block body %}中,并在代码一开始”继承”上面的”layout.html”:

  1. {% extends "layout.html" %}
  2. {% block body %}
  3. {% if name %}
  4. <h1>Hello {{ name }}!</h1>
  5. {% else %}
  6. <h1>Hello World!</h1>
  7. {% endif %}
  8. {% endblock %}

HTML自动转义

我们看下下面的代码:

  1. @app.route('/')
  2. def index():
  3. return '<div>Hello %s</div>' % '<em>Flask</em>'

打开页面,你会看到”Hello Flask”字样,而且”Flask”是斜体的,因为我们加了<em>标签。但有时我们并不想让这些HTML标签自动转义,特别是传递表单参数时,很容易导致HTML注入的漏洞。我们把上面的代码改下,引入”Markup”类:

  1. from flask import Flask, Markup
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. return Markup('<div>Hello %s</div>') % '<em>Flask</em>'

再次打开页面,标签显示在页面上了。Markup还有很多方法,比如escape()呈现HTML标签, striptags()去除HTML标签。这里就不一一列举了。