一:视图:

1:基本使用

1.1:安装 flask-restful:

pip install flask-restful

1.2: 构建RESTAPI
  • 1:创建app对象。
  • 2:将app对象包装成具备restful风格的组件对象。
  • 3:定义类视图继承于Resourse。
  • 4:给视图添加路由信息。
  • 注意点:当返回一个字典时,flask_restful会自动封装成json。
  • 类视图响应的 content-type 默认变为 JSON形式
  • endpoint表示起别名:给这个视图起一个别名。
from flask import Flask
from flask_restful import Api, Resource

# 1: 创建app对象
app = Flask(__name__)

# 2:将app对象包装成具备restful风格的组件对象api
api = Api(app)

# 3:定义类视图继承于:Resourse
class DemoResourse(Resource):

    def get(self):
        return {'get': "get_message"}

    def post(self):
        return {'post': "post_message"}

# 4:给视图添加路由信息
api.add_resource(DemoResourse, '/',endpoint= "myresource")

@app.route('/login')
def login():
    print(app.url_map)
    return ""

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

原来是类名的小写,现在改成自己定义的这个名字了。
在这里插入图片描述

1.3:flask_restful返回时中文编码问题:
  • 在flask_restful中,output_json控制返回的格式:
  • app.config[‘RESTFUL_JSON’] = {“ensure_ascii”: False} 解决中文编码问题。

源码解析:
在这里插入图片描述
根据流程,发现就是字典中,没有取消转换ASCII的配置。

解决方案:
增加配置项:

# 配置转换成中文
app.config['RESTFUL_JSON'] = {"ensure_ascii": False}

2:类视图装饰器

  • 方案一:method_decorators列表的形式。
  • 方案二:method_decorators字典的形式。
  • 注意:装饰器装饰的顺序和执行的顺序,装饰的顺序是,先装饰列表前面的,再装饰后面的,执行顺序是先执行后面的,再执行前面的。

<案例一>使用列表装饰,并且查看装饰器的执行过程。

from flask import Flask
from flask_restful import Api, Resource

"""
# 需求:类视图添加装饰器
"""
app = Flask(__name__)
api = Api(app)

# 装饰器一
def mydecorator(func):
    print("第一个装饰器装饰了")
    def wrapper(*args, **kwargs):
        print("mydecorator dispatch")
        return func(*args, **kwargs)
    return wrapper

# 装饰器二:
def mydecorator2(func):
    print("第二个装饰器也装饰了")
    def wrapper(*args, **kwargs):
        print("mydecorator2 dispatch")
        return func(*args, **kwargs)
    return wrapper


class DemoResource(Resource):

    # 方案一:给类视图的所有方法添加装饰器
    method_decorators = [mydecorator, mydecorator2]
    def get(self):
        return {"get": "get message"}

    def post(self):
        return {"post": "post body"}

api.add_resource(DemoResource, '/')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

执行效果来看:
在这里插入图片描述
<案例二>: 给指定添加装饰器:
分析源码:
在这里插入图片描述
分析源码得到,我们也可以将method_decorators赋值成一个字典,键是请求方式,值是个列表,列表里面是多个视图。
因此也可以这样进行装饰。

class DemoResource(Resource):

    # 方案一:给类视图的所有方法添加装饰器
    # method_decorators = [mydecorator, mydecorator2]
    method_decorators = {
        'get': [mydecorator, mydecorator2],
        'post': [mydecorator]
    }
    def get(self):
        return {"get": "get message"}

    def post(self):
        return {"post": "post body"}

3:蓝图和类视图

  • 创建蓝图对象:user_dp = Blueprint(“user”, name, url_prefix="/user")
  • 将蓝图对象包装成api对象: api = Api(user_dp)
  • 给蓝图对象添加路由信息: api.add_resource(DemoResource, ‘/info’)
  • 注册蓝图: app.register_blueprint(user_dp)

1: 主函数代码:

from user import user_dp
from flask import Flask, make_response, Response, request

app = Flask(__name__)

# 4: 注册蓝图
app.register_blueprint(user_dp)


if __name__ == '__main__':
    print(app.url_map)
    app.run(host='0.0.0.0', port=8000, debug=True)

2:__init__初始化文件:

from flask import Blueprint
from flask_restful import Api

# 1:创建蓝图对象
user_dp = Blueprint("user", __name__, url_prefix="/user")

# 2: 将蓝图对象包装成api对象
api = Api(user_dp)

# 3:给蓝图对象添加路由信息
from .views import DemoResource
api.add_resource(DemoResource, '/info')

3:视图文件:

from flask_restful import  Resource

class DemoResource(Resource):
    def get(self):
        return "Demo"

二:请求:

1:请求的基本使用:

  • 1: 创建解析对象: parser = RequestParser()
  • 2: 添加解析参数和规则: parser.add_argument(“name”, required=True, location=“json”)
  • 3:开始解析获取解析结果: ret = parser.parse_args()
  • 4:从解析结果中获取值: name = ret.name 或者 age = ret[‘age’]
from flask import Flask
from flask_restful import Api, Resource
from flask_restful.reqparse import RequestParser

app = Flask(__name__)
api = Api(app)

class DemoResource(Resource):

    def get(self):
        # 1: 创建解析对象
        parser = RequestParser()

        # 2: 添加解析参数和规则:location指的是前端传递的格式:json, args, text, form, files
        parser.add_argument("name", required=True, location="json")
        parser.add_argument("age", required=18, location="json")

        # 3:开始解析,获取解析结果
        ret = parser.parse_args()

        # 4: 从解析结果中提取参数值
        name = ret.name
        age = ret['age']
        print(name)
        print(age)
        return {"foo": "get"}
    def post(self):
        return {"foo": "post"}

api.add_resource(DemoResource, '/')

if __name__ == '__main__':
    print(app.url_map)
    app.run(host='0.0.0.0', port=8000, debug=True)

2:type的三中类型:

  • 1: python自带的类型
  • 2:flask_restful自己内置的
  • 3:自己定义的函数/类。
 # python自带的类型:
        parser.add_argument("name", required=True, location="json", type= str)
        parser.add_argument("age", required=True, location="json", type= int)
#flask_restful自带的类型:
        parser.add_argument("age", required=True, location="json", type=int_range(0, 100))
        parser.add_argument("gender", required=True, location="json", type=boolean)
        parser.add_argument("birthday", required=True, location="json", type=date)
        parser.add_argument("mobile", required=True, location="json", type=regex(r'^1[3-9]\d{9}$'))

# 类的外部定义一个函数:
def get_user(value):
    if re.match(r'^user', value):
        return value[5:]
    else:
        raise ValueError("invalid user")


 # 自定义的函数/类
        parser.add_argument("user", required=True, location="json", type=get_user)

三:响应:

1:序列化

<方案一>:自定义一个类,然后自定义序列化规则,然后创建类的对象,最后将对象和规则传入marshal函数中。

from flask import Flask
from flask_restful import Api, Resource, marshal,marshal_with, fields
# marshal是序列化函数,marshal_with是装饰器。
# 序列化字段模块fields

# 需求,将模型类对象转换成字典,flask_restful内部的output_json会转换成字符串。
app = Flask(__name__)
api = Api(app)

class Person(object):
    def __init__(self):
        self.name = "curry"
        self.age = 18
        self.height = 185.6
        self.mylist = [30, 20, 50]
        self.mydict = {
            "gender": True
        }

user_dict = {
    "name": fields.String,
    "age": fields.Integer(default=28),
    "height": fields.Float,
    "mylist": fields.List(fields.Integer),
    "mydict": {"gender": fields.Boolean}
}

class DemoResource(Resource):
    def get(self):
        # 1: 创建一个对象
        user = Person()
        # 2:使用marshal函数,传入被序列化对象和序列化规则
        return marshal(user, user_dict)
    def post(self):
        return {"foo": "post"}

api.add_resource(DemoResource, '/')

if __name__ == '__main__':
    print(app.url_map)
    app.run(host="0.0.0.0", port=8000,debug=True)

<方案二>: 使用marshal_with装饰器:

method_decorators = {
        "post": [marshal_with(user_dict)]
    }  
from flask import Flask
from flask_restful import Api, Resource, marshal,marshal_with, fields
# marshal是序列化函数,marshal_with是装饰器。
# 序列化字段模块fields

# 需求,将模型类对象转换成字典,flask_restful内部的output_json会转换成字符串。
app = Flask(__name__)
api = Api(app)

class Person(object):
    def __init__(self):
        self.name = "curry"
        self.age = 18
        self.height = 185.6
        self.mylist = [30, 20, 50]
        self.mydict = {
            "gender": True
        }

user_dict = {
    "name": fields.String,
    "age": fields.Integer(default=28),
    "height": fields.Float,
    "mylist": fields.List(fields.Integer),
    "mydict": {"gender": fields.Boolean}
}

class DemoResource(Resource):

    method_decorators = {
        "post": [marshal_with(user_dict)]
    }

    def get(self):
        # 1: 创建一个对象
        user = Person()
        # 2:使用marshal函数,传入被序列化对象和序列化规则
        return marshal(user, user_dict)
    def post(self):
        user = Person()
        return user
    

api.add_resource(DemoResource, '/')

if __name__ == '__main__':
    print(app.url_map)
    app.run(host="0.0.0.0", port=8000,debug=True)

<方案三>:自己转换(推荐)

from flask import Flask
from flask_restful import Api, Resource, marshal,marshal_with, fields
# marshal是序列化函数,marshal_with是装饰器。
# 序列化字段模块fields

# 需求,将模型类对象转换成字典,flask_restful内部的output_json会转换成字符串。
app = Flask(__name__)
api = Api(app)

class Person(object):
    def __init__(self):
        self.name = "curry"
        self.age = 18
        self.height = 185.6
        self.mylist = [30, 20, 50]
        self.mydict = {
            "gender": True
        }
    def to_dict(self):
        my_dict = {
            "name": self.name,
            "age": self.age,
            "height": self.height,
            "mylist": self.mylist,
            "mydict": self.mydict
        }
        return my_dict

user_dict = {
    "name": fields.String,
    "age": fields.Integer(default=28),
    "height": fields.Float,
    "mylist": fields.List(fields.Integer),
    "mydict": {"gender": fields.Boolean}
}

class DemoResource(Resource):
    def get(self):
        # 1: 创建一个对象
        user = Person()
        # 2:将对象转化成字典返回
        return user.to_dict()

api.add_resource(DemoResource, '/')

if __name__ == '__main__':
    print(app.url_map)
    app.run(host="0.0.0.0", port=8000,debug=True)

2:自定义JSON

方案一:自定义output_json,然后使用语法糖进行装饰。@api.representation(‘application/json’)。

from flask import Flask, current_app, make_response
from flask_restful import Api, Resource, output_json
from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps


app = Flask(__name__)
api = Api(app)

"""
需求:修改JSON的返回个格式

解决方案:使用装饰器拦截output_json底层源代码,定义json格式。

"""
@api.representation('application/json')
def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    settings = current_app.config.get('RESTFUL_JSON', {})

    if "messgae" not in data:
        data = {
            "message": "ok",
            "data": data
        }

    if current_app.debug:
        settings.setdefault('indent', 4)
        settings.setdefault('sort_keys', not PY3)

    dumped = dumps(data, **settings) + "\n"

    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return resp

class DemoResource(Resource):
    def get(self):
        return {"foo": "get"}
    def post(self):
        return {"foo": "post"}

api.add_resource(DemoResource, '/')

if __name__ == '__main__':
    print(app.url_map)
    app.run(host="0.0.0.0",debug=True, port=8000)

<方案二>:将代码封装起来,然后使用装饰器进行主动装饰。
新建utils.py


from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps

def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    settings = current_app.config.get('RESTFUL_JSON', {})

    if "messgae" not in data:
        data = {
            "message": "ok",
            "data": data
        }

    if current_app.debug:
        settings.setdefault('indent', 4)
        settings.setdefault('sort_keys', not PY3)

    dumped = dumps(data, **settings) + "\n"

    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return resp

在主要main.py中主动装饰:

# 方案二:装饰器主动装饰
api.representation(mediatype="application/json")(output_json)
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐