路由的基本使用


1. 添加路由的两种方式

  • 方式一 -> 通过装饰器添加路由

# app.py

from flask import Flask

app = Flask(__name__)


# 路由的配置
@app.route('/login') # 路由地址
def login():  # 视图函数
    return 'login'


@app.route('/')
def index():
    return 'index'


if __name__ == '__main__':
    app.run()  # 启动 Flask

  • 方式二 -> 通过 app.add_url_rule() 方法添加路由

    • 其实 @app.route() 装饰器本质上也是使用了 .add_url_rule() 方法添加路由的

# app.py

from flask import Flask

app = Flask(__name__)


def login():
    return 'login'


app.add_url_rule(rule='/login', endpoint=None, view_func=login) # 添加路由 -> rule: 路由地址, endpoint: 路由别名, view_func: 视图函数


def index():
    return 'index'


app.add_url_rule(rule='/index', endpoint=None, view_func=index) # 添加路由 -> rule: 路由地址, endpoint: 路由别名, view_func: 视图函数

if __name__ == '__main__':
    app.run()  # 启动 Flask

  • 使用方式二仿照Django的路由写法

# app.py

from flask import Flask

app = Flask(__name__)


def login():
    return 'login'


def index():
    return 'index'


urls = [
    ('/login', None, login),
    ('/index', None, index),
]

for url in urls:
app.add_url_rule(rule=url[0], endpoint=url[1], view_func=url[2]) # 添加路由 -> rule: 路由地址, endpoint: 路由别名, view_func: 视图函数

if __name__ == '__main__':
    app.run()

@app.route 和 app.add_url_rule 的路由参数



参数
说明
rule
路由地址(即: url规则)
view_func
视图函数名
methods
设置允许xxx请求访问当前路由,默认 GET 请求
defaults
默认值,当URL中无参数,函数需要参数时,使用defaults={'key': 'value'}为函数提供参数
endpoint
路由别名,相当于Django路由中的name,用于反向生成 url
strict_slashes
对URL最后的 / 符号是否严格要求
redirect_to
重定向到指定地址
subdomain
子域名访问

1. rule

  • 路由地址

  • @app.route

# app.py

from flask import Flask

app = Flask(__name__)


@app.route(rule='/login')
def login():
    return 'login'


if __name__ == '__main__':
    app.run()

  • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)


def login():
    return 'login'


app.add_url_rule(rule='/login', view_func=login)

if __name__ == '__main__':
    app.run()

2. view_func

  • 视图函数名

  • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)


def login():
    return 'login'


app.add_url_rule(rule='/login', view_func=login)

if __name__ == '__main__':
    app.run()

3. methods

  • 设置允许xxx请求访问当前路由,默认 GET 请求

  • @app.route

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/login', methods=['GET', 'POST'])
def login():
    return 'login'


if __name__ == '__main__':
    app.run()

  • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)


def login():
    return 'login'


app.add_url_rule(rule='/login', view_func=login, methods=['GET', 'POST'])

if __name__ == '__main__':
    app.run()

4. defaults

  • 默认值,当URL中无参数,函数需要参数时,使用defaults={'key': 'value'}为函数提供参数

  • @app.route

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/login', defaults={'name': 'Kevin', 'password': 123})
def login(name, password):
    print(name, password)  # Kevin 123
    return 'login'


if __name__ == '__main__':
    app.run()

  • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)


def login(name, password):
    print(name, password)  # Kevin 123
    return 'login'


app.add_url_rule(rule='/login', view_func=login, defaults={'name': 'Kevin', 'password': 123})

if __name__ == '__main__':
    app.run()

5. endpoint

  • 路由别名,相当于Django路由中的name,用于反向生成 url

  • endpoint 默认值: 视图函数

  • @app.route

# app.py

from flask import Flask, url_for

app = Flask(__name__)


@app.route('/login', endpoint='login_url')
def login():
    print(url_for('login_url'))  # /login
    return 'login'


if __name__ == '__main__':
    app.run()

  • app.add_url_rule

# app.py

from flask import Flask, url_for

app = Flask(__name__)


def login():
    print(url_for('login_url'))  # /login
    return 'login'


app.add_url_rule(rule='/login', view_func=login, endpoint='login_url')

if __name__ == '__main__':
    app.run()

6. strict_slashes

  • 对URL最后的 / 符号是否严格要求

  • 默认值: None

  • 值: 
    • None: 开启严格模式 -> 当 url 后面没有 / 时,不能加 / 进行访问
    • True: 开启严格模式 -> 当 url 后面没有 / 时,不能加 / 进行访问
    • False: 关闭严格模式 -> 当 url 后面没有 / 时,可以加 / 进行访问

  • @app.route

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/login', strict_slashes=False)
def login():
    return 'login'


if __name__ == '__main__':
    app.run()

  • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)


def login():
    return 'login'


app.add_url_rule(rule='/login', view_func=login, strict_slashes=False)

if __name__ == '__main__':
    app.run()

7. redirect_to

  • 重定向到指定地址

  • 使用场景: 当有了新系统或网站,旧的系统或网站不能立刻停掉,当访问旧系统或网站的时候重定向到新的系统或网站

  • @app.route

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/index', redirect_to='/new_index')
def index():
    return 'index'


@app.route('/new_index')
def new_index():
    return 'new_index'


if __name__ == '__main__':
    app.run()

  • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)


def index():
    return 'index'


app.add_url_rule(rule='/index', view_func=index, redirect_to='/new_index')


@app.route('/new_index')
def new_index():
    return 'new_index'


app.add_url_rule(rule='/index', view_func=new_index)

if __name__ == '__main__':
    app.run()

8. subdomain

  • 子域名访问

  • 添加子域名



  • 刷新子域名

    • ipconfig /flushdns


  • 编写子域名访问

    • @app.route

# app.py

from flask import Flask

app = Flask(__name__)
app.config['SERVER_NAME'] = 'kevin.com:5000'  # 配置域名 + 端口,一定要添加该配置,否则无法生效


# http://admin.kevin.com:5000/
@app.route('/', subdomain='admin')  # 设置子域名
def admin_index():
    return 'admin_index'


# http://web.kevin.com:5000/
@app.route('/', subdomain='web')  # 设置子域名
def web_index():
    return 'web_index'


# http://任意前缀.kevin.com:5000/dynamic
@app.route('/dynamic', subdomain='<prefix_name>')  # <prefix_name> 表示匹配任意的子域名前缀
def prefix_index(prefix_name):
    return prefix_name + '_index'


if __name__ == '__main__':
    app.run()

    • app.add_url_rule

# app.py

from flask import Flask

app = Flask(__name__)
app.config['SERVER_NAME'] = 'kevin.com:5000'  # 配置域名 + 端口,一定要添加该配置,否则无法生效


def admin_index():
    return 'admin_index'


# http://admin.kevin.com:5000/
app.add_url_rule(rule='/', view_func=admin_index, subdomain='admin')  # 设置子域名


def web_index():
    return 'web_index'


# http://web.kevin.com:5000/
app.add_url_rule(rule='/', view_func=web_index, subdomain='web')  # 设置子域名


def prefix_index(prefix_name):
    return prefix_name + '_index'


# http://任意前缀.kevin.com:5000/dynamic
app.add_url_rule(rule='/dynamic', view_func=prefix_index, subdomain='<prefix_name>')  # <prefix_name> 表示匹配任意的子域名前缀

if __name__ == '__main__':
    app.run()

带参数的URL


注意: 如果使用了带参数的URL,那么视图函数一定要接收这个参数,不然就会报错

1. 语法

# 没有指定数据类型的参数,默认该参数为 string 类型
@app.route('/user/<参数名>')

# 指定数据类型的参数
@app.route('/user/<数据类型:参数名>')

2. 常用的数据类型

@app.route('/user/<username>')  # 如果不指定数据类型,默认使用string类型

@app.route('/user/<string:username>')  # string -> 字符串

@app.route('/post/<int:post_id>')  # int -> 整形

@app.route('/post/<float:post_id>')  # float -> 浮点型

@app.route('/post/<path:url>')  # 路径类型

3. 路由系统的数据类型与转换器的对应关系

# UnicodeConverter 等,这些都是转换器

DEFAULT_CONVERTERS = {
    'default': UnicodeConverter,
    'string':  UnicodeConverter,
    'any':     AnyConverter,
    'path':    PathConverter,
    'int':     IntegerConverter,
    'float':   FloatConverter,
    'uuid':    UUIDConverter,
}

4. 使用例子一

  • 接收一个参数

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/news/<int:nid>')
def news(nid):  # 一定要接收URL中的参数否则会报错
    print(nid)  # 10
    return 'news'


if __name__ == '__main__':
    app.run()

5. 使用例子二

  • 接收多个参数

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/news/<int:nid>/<int:uid>')
def news(nid, uid):  # 一定要接收URL中的参数否则会报错
    print(nid)  # 10
    print(uid)  # 5
    return 'news'


if __name__ == '__main__':
    app.run()

自定义正则路由匹配


执行流程:
  1. 用户发送请求
  2. Flask内部进行正则匹配
  3. 匹配成功后调用 to_python(正则匹配的结果) 方法
  4. 将 to_python() 方法的返回值交给视图函数的参数
  5. 使用url_for反向生成URL时会触发 to_url() 方法,帮助我们反向生成url

# app.py

from flask import Flask, url_for
from werkzeug.routing import BaseConverter

app = Flask(import_name=__name__)


# 步骤一: 定制转换器
class RegexConverter(BaseConverter):
"""
    自定义正则路由匹配
    """

    def __init__(self, map, regex):
        super(RegexConverter, self).__init__(map)
        self.regex = regex  # '\d+' -> 接收你所传递的正则表达式,Flask会自动进行正则匹配

    def to_python(self, value):
 """
        路由匹配成功后执行该方法,将匹配到的值返回给视图函数
        :param value:  匹配成功的值
        """
        return int(value)

    def to_url(self, value):
"""
        使用url_for反向生成URL时执行该方法,url_for所传递的参数经过该方法进行处理,返回的值是用于生成URL中的参数
        :param value: url_for 传递过来的参数
        """
        val = super(RegexConverter, self).to_url(value)  # 888
        return val


# 步骤二: 将转换器添加到Flask中
app.url_map.converters['reg'] = RegexConverter


# 步骤三: 使用自定义正则
@app.route('/index/<reg("\d+"):nid>')  # reg("\d+") 实例化对象,执行 RegexConverter 构造方法
def index(nid):
    print(nid# url匹配到的参数
    url = url_for('index', nid='888')  # 反向生成url,触发 to_url 方法
    print(url)  # /index/888
    return 'Index'


if __name__ == '__main__':
    app.run()

命名URL(URL反向查询)


命名URL(URL反向解析)通俗理解: 通过url别名反向查找出实际的URL

命名URL(URL反向解析)的好处: 当我们修改了路由中的url路径也不会影响到视图函数或模板中使用了该路径的地方,因为是通过url别名反向查找出实际的URL

在以后日常开发中都要使用 命名URL(URL反向解析)

1. 命名URL

  • endpoint 相当于 Django 路由中的 name

  • endpoint 的默认值: 它所绑定的视图函数名(即: 如果 endpoint 没有指定,那么 endpoint 会默认指向它所绑定的视图函数名

  • endpoint 的值不能重复

  • 语法: endpoint='url别名'

# app.py

from flask import Flask

app = Flask(__name__)


@app.route('/index/', endpoint='index_url')
def index():
    return 'index'


if __name__ == '__main__':
    app.run()

2. URL反向查询(URL不带参数)

  • 通过 url_for 反向查询出url别名所指定的url路径

  • 语法: url_for='url别名'

# app.py

from flask import Flask, url_for

app = Flask(__name__)


@app.route('/index/', endpoint='index_url')
def index():
    this_url = url_for('index_url')  # 通过url别名反向查询出它的url
    print(this_url)  # /index/
    return 'index'


if __name__ == '__main__':
    app.run()

3. URL反向查询(带参数的URL)

# app.py

from flask import Flask, url_for

app = Flask(__name__)


@app.route('/index/<int:uid>/<int:nid>')
def index(uid, nid):
    this_url = url_for('index', uid=1, nid=5)  # 通过url别名反向查询出它的url
    print(this_url)  # /index/1/5
    return 'index'


if __name__ == '__main__':
    app.run()

4. URL反向查询(没有指定endpoint

  • 如果没有指定 endpoint 那么默认使用视图函数名进行反向查询,因为 endpoint 默认指向它所绑定的视图函数名

# app.py

from flask import Flask, url_for

app = Flask(__name__)


@app.route('/index/')
def index():
    this_url = url_for('index')  # 如果没有指定 endpoint 那么默认使用视图函数名进行反向查询,因为 endpoint 默认指向它所绑定的视图函数名
    print(this_url)  # /index/
    return 'index'


if __name__ == '__main__':
    app.run()