Loading

Flask学习笔记(2)

路由

在flask中,使用 @route() 装饰器来把函数绑定到URL。

@app.route('/home') #声明路由
def index(): # 声明视图函数
    return '<h1>Hello, Flask!</h1>'

注意:路由和视图的名称必须全局唯一,不能出现重复。

除了可以使用装饰器的方式注册路由,还可以使用app的add_url_rule方法。

def hello():
    return 'Hello, Flask!'

app.add_url_rule('/hello', view_func=hello)

查询路由信息

有两种方式可以查看当前应用的路由信息

  • 命令行方式

    flask routes
    

    输出内容如下:

    Endpoint  Methods  Rule
    --------  -------  -----------------------
    index     GET      /
    static    GET      /static/<path:filename>
    
  • 在程序中获取

    在应用的url_map属性中保存着当前flask应用所有的映射信息,可以读取这个属性获取路由信息

    print(app.url_map)
    

    遍历所有路由信息:

    for rule in app.url_map.iter_rules():
        print(rule.endpoint, rule.rule)
    

请求方式

路由默认的请求方式为

  • GET
  • OPTIONS
  • HEAD

使用 methods 参数可以指定一个接口的请求方式

@app.route('/', methods=["POST"])
def hello_world():
    return 'Hello World!'

蓝图

当flask程序越来越复杂,我们需要对程序进行模块化处理,在Flask中使用Blueprint来分模块组织管理。

蓝图可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:

  • 一个应用可以具有多个Blueprint。
  • 可以将一个Blueprint注册到任何一个未使用的URL下,比如"/hello"、"/user"。
  • Blueprint可以单独具有自己的模板、静态文件或者其他的通用的操作方法,它并不是必须要实现应用的视图和函数。
  • 在一个应用初始化时,就应该注册需要使用的Blueprint。

使用方式

使用蓝图可以分为三个步骤:

  1. 创建一个蓝图对象 users/__init__.py
from flask import Blueprint
users_bp = Blueprint('users', __name__)
from . import views
  1. 在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模板过滤器 users/views.py
@user_bp.route('/profile')
def get_profile():
    return 'user profile!'
  1. 在应用对象上注册蓝图对象 app.py
app.register_blueprint(user_bp)

目录(包)的方式使用蓝图

对应一个打算包含多个文件的蓝图,可以将创建蓝图对象放到python包的 __init__.py 文件中

--------- project #工程目录
  |------ app.py  #启动文件
  |------ users    #用户蓝图
  |  |--- __init__.py #此处创建蓝图对象
  |  |...
  |------ goods   #商品蓝图
  |  |--- __init__.py 
  |...

示例:

新建包goods,__init__.py文件内容如下

from flask import Blueprint

goods_bp = Blueprint('goods', __name__)

from . import views # 此处导入代码必须放在最后,如果放在最上方,会出现循环引用的问题

在goods目录下,新建 views.py 文件内容如下:

from . import goods_bp

@goods_bp.route('/goods')
def get_goods():
    return 'get goods'

app.py内容如下:

from flask import Flask
from goods import goods_bp
app = Flask(__name__)

app.register_blueprint(goods_bp)

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

蓝图内部静态文件

和应用对象不同,蓝图对象创建时不会默认注册静态目录的路由,需要我们在创建时指定 static_folder 参数。

示例:

goods_bp = Blueprint('goods', __name__, static_folder='static_file', template_folder='goods_templates')
app.register_blueprint(goods_bp, url_prefix='/goods')

转换器

动态路由

通过把 URL 的一部分标记为 <variable_name> 就可以在 URL 中添加变量。标记的部分会作为关键字参数传递给函数。通过使用 <converter:variable_name> ,可以选择性的加上一个转换器,为变量指定规则。

from flask import Flask

app = Flask(__name__)


@app.route('/users/<user_id>')
def hello_world(user_id):
    print(type(user_id))  # <class 'str'>
    return 'users {} '.format(user_id)


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

此处 user_id 作为参数名传入视图,默认为字符串类型。

默认转换器

除了默认的字符串类型之外,Flask还提供了如下其他类型的转换器。

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

转换器对应的含义:

转换器 含义
default 接受字符串,默认转换器
string 接受字符串,跟默认一样
any 限定url中接收参数的值
path 可以接受斜线
int 接受整数
float 接受浮点数
uuid 只接收uuid类型的字符串

示例:

@app.route('/users/<path:user_id>')
def hello_world(user_id):
    print(type(user_id))
    return 'users {} '.format(user_id)

自定义转换器

当系统提供的转换器并不能满足我们的要求时,此时我们需要自定义转换器。需要用到Flask的转换器基类BaseConverter

自定义转换器主要做3步:

  1. 创建转换器类

    from werkzeug.routing import BaseConverter
    class MobileConverter(BaseConverter):
        regex = r'1[3-9]\d{9}'  # 转换器的正则规则
    
    

    注意:regex名字是固定的

  2. 将转换器添加到converters中

    app.url_map.converters['mobile'] = MobileConverter
    
  3. 使用自定义的转换器

    @app.route('/message/<mobile:mobile_num>')
    def send_message(mobile_num):
        print(type(mobile_num))
        return 'mobile num  {} '.format(mobile_num)
    

Request

如果想要获取其他地方的参数,可以通过Flask提供的全局对象 request 来获取。request 中不同的属性对应不同位置的请求参数。

常见的属性和说明如下:

属性 说明
data 记录请求的数据,并转换为字符串
form 请求中的表单数据
args 请求中的查询参数
cookies 请求中的cookie信息
headers 请求中的报文头
method 请求使用的HTTP方法
url 记录请求的URL地址
files 请求上传的文件

示例:

@app.route('/users')
def get_user_id():
    user_id = request.args.get('user_id')
    return 'your user id is {} '.format(user_id)

接受上传文件示例:

@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']
    # with open('./test.png', 'wb') as new_file:
    #     new_file.write(file.read())
    file.save('./test.png') # 可以直接调用save方法保存
    return 'ok'

模板

在项目的目录下新建名为templates的文件夹,并在此文件夹下新建名为index.html的html文件。

内容如下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>我的模板内容</h1>
    名字: <span>{{ name }}</span> <br>
    年龄: <span>{{ age }}</span> <br>

</body>
</html>

渲染数据到模板

@app.route('/')
def home():
    uname = '张三'
    uage = '20'
    return render_template('index.html', name=uname, age=uage)
posted @ 2021-08-25 14:44  charlatte  阅读(96)  评论(0编辑  收藏  举报