二、Flask_路由定义与http的请求/响应

 

1. 路由定义

1.1 路由基本定义

...
# 指定访问路径为 demo
@app.route('/demo')
def demo():
    return 'demo'
...

1.2 路由传递参数(两种)

  1. 没有限定类型
    #
    @app.route('/user/<user_id>')
    def user_info(user_id):
        return 'hello %s' % user_id
  2. 限定数据类型
    #
    @app.route('/user/<int:user_id>')
    def user_info(user_id):
        return 'hello %d' % user_id

     

1.3 路由限定请求方式

#
@app.route('/demo', methods=['GET', 'POST'])
def demo():
    # 直接从请求中取到请求方式并返回
    return request.method

 

1.4 正则匹配路由

在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问

具体实现步骤为:

  • 导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录

  • 自定义转换器:自定义类继承于转换器基类

  • 添加转换器到默认的转换器字典中

  • 使用自定义转换器实现自定义匹配规则

代码实现

  1. 导入转换器基类
    from werkzeug.routing import BaseConverter
  2. 自定义转换器
    # 自定义正则转换器
    from werkzeug.routing import BaseConverter
    class RegexConverter(BaseConverter):
        def __init__(self,url_map,*args):
            super(RegexConverter, self).__init__(url_map)
            # 正则参数
            self.regex = args[0]
  3. 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re
    # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
    app.url_map.converters['re'] = RegexConverter
  4. 使用转换器去实现自定义匹配规则
    # 当前此处定义的规则是:手机号码
    
    # 正则匹配路由
    @app.route("/login/<re('1\d{10}'):mobile>")
    def login(mobile):
        return mobile

     

1.5 系统自动转换器

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

系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。

 

2 http请求与响应

文档:http://docs.jinkan.org/docs/flask/api.html#flask.request

2.1 请求

  • request:flask中代表当前请求的 request 对象

  • 作用:在视图函数中取出本次请求数据

  • 导入:from flask import request

获取方法

request.属性

 

 常用的属性如下:

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

 属性下有属性

使用方法 request.args.属性(参数)  

属性 说明 类型 举例
get() 获取一个参数的一个值   request.args.get("username")
getlist() 获取一个参数的多个值 List request.args.getlist("love")
to_dict( ) 把传递过来的数据抓换成原生的字典 Dict request.args.to_dict()
to_list( )     request.headers.to_list()

 

 

from flask import Flask
# 新增一个配置文件,在配置文件中设置配置信息
from config import Config
from flask import request
# from collections import OrderedDict  # 有序字典

app = Flask(__name__)

# 调用app.config加载配置
app.config.from_object(Config)


from werkzeug.routing import BaseConverter

class RegexConverter(BaseConverter):
    def __init__(self,url_map,*args):
        super(RegexConverter, self).__init__(url_map)
        # 正则参数
        self.regex = args[0]

# converter["路由转换器名称"] = 实现路由转换功能的自定义类
app.url_map.converters['re'] = RegexConverter
# 绑定路由
@app.route("/")
def index():
    return "hello flask"


# 默认情况下,路由使用的就是关键字参数,也叫"命名路由"
# router(路由地址, http请求方式 )
@app.route("/list/<int:page>/<string:content>",methods=["GET","POST"])
def mylist(content,page):
    return "第%s页<br>内容:%s" % (page,content)

# 正则匹配路由
@app.route("/login/<re('1\d{10}'):mobile>")
def login(mobile):
    return mobile

"""获取客户端的请求"""
@app.route("/request")
def req1():
    """获取查询字符串"""
    query_string = request.args
    # print(query_string)
    """打印效果: ImmutableMultiDict([('username', 'xiaoming'), ('user_id', '1')])"""

    # 获取一个参数的一个值
    username = request.args.get("username")
    # print(username)
    """打印效果: xiaoming"""

    # 获取一个参数的多个值
    # http://www.luffycity.cn:5000/request?username=xiaoming&user_id=1&love=吹牛&love=睡觉
    love = request.args.getlist("love")
    # print(love)
    """打印效果: ['吹牛', '睡觉']"""


    # 把传递过来的数据抓换成原生的字典
    data = request.args.to_dict()
    # print(data)
    """打印效果: {'username': 'xiaoming', 'user_id': '1', 'love': '吹牛'} """

    return "ok"

@app.route("/request2",methods=["POST"])
def req2():
    """获取post数据和请求头"""
    # print( request.data )
    # """打印结果:
    # b'{\n\t"username":"xiaoming",\n\t"age":18,\n\t"sex":1\n}'
    # """
    #
    # import json
    # from flask import json
    # data = json.loads(request.data)
    # print(data)
    # """打印结果:
    # {'username': 'xiaoming', 'age': 18, 'sex': 1}
    #
    # """
    #
    # """获取请求行数据"""
    # print( request.headers )
    # print( request.headers.to_list() )


    """获取上传文件"""
    print( request.files )
    print( request.files.get("avatar") )
    """打印效果: 
    ImmutableMultiDict([('avatar', <FileStorage: 'avatar.png' ('image/png')>)])
    <FileStorage: 'avatar.png' ('image/png')>
    """

    return "ok"

if __name__ == '__main__':
    app.run()
测试代码

 

2.2 响应

flask默认支持2种响应方式:

  1. 数据响应: 默认响应html文本,也可以返回 JSON格式
  2. 页面响应: 重定向(url_for)

响应的时候,flask也支持自定义http响应状态码

2.2.1 数据响应

响应html文本

@app.route("/")
def index():
    # [默认支持]响应html文本
    return "<img src='http://flask.pocoo.org/static/logo.png'>"

返回json格式

from flask import Flask, request, jsonify

@app.route("/")
def index():
    # 也可以响应json格式代码
    data = [
        {"id":1,"username":"liulaoshi","age":18},
        {"id":2,"username":"liulaoshi","age":17},
        {"id":3,"username":"liulaoshi","age":16},
        {"id":4,"username":"liulaoshi","age":15},
    ]
    return jsonify(data)

 

2.2.2 重定向

重定向到外部网站

# 页面跳转响应
@app.route("/user")
def user():
    # 页面跳转 redirect函数就是response对象的页面跳转的封装
    # Location: http://www.baidu.com
    return redirect("http://www.baidu.com")

 

重定向到视图函数

  1. 可以直接填写自己 url 路径
  2. 使用url_for实现视图方法之间的内部跳转 url_for("视图方法名") 
    from flask import redirect,url_for
    
    @app.route('/user/<user_id>')
    def user_info(user_id):
        return 'hello %d' % user_id
    
    @app.route("/index")
    def index():
        # 1. 跳转到站内地址,例如其他页面
        return redirect("/response")
        # 2.1 跳转到站内视图函数对应的页面中[没有附带地址参数]
        return redirect(url_for("index"))
        # 2.2 跳转到站内视图函数对应的页面中[有附带地址参数,通过命名参数传递路由参数]
        return redirect(url_for('user_info', user_id=100))

     

2.2.3 自定义状态码

在 Flask 中,可以很方便的返回自定义状态码,以实现不符合 http 协议的状态码,例如:status code: 666

@app.route('/demo')
def demo():
    return '状态码为 666', 400

 

posted @ 2019-05-30 20:18  yijue_lu  阅读(843)  评论(0编辑  收藏  举报