Flask-Restful超详解、序列化

前言

这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题

于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。

微信小程序搜索:Python面试宝典

或可关注原创个人博客:https://lienze.tech

也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习

Flask-Restful

Flask-RESTful 是一个可以简化 APIs 的构建的 Flask 扩展,类似django的drf,需要进行安装

pip install flask-restful

请求回顾

方法url示例解释
GEThttp://[hostname]/todo/api/v1.0/tasks
http://[hostname]/todo/api/v1.0/tasks/[task_id]
检索任务列表
检索某个任务
POSThttp://[hostname]/todo/api/v1.0/tasks创建新任务
PUThttp://[hostname]/todo/api/v1.0/tasks/[task_id]更新任务
DELETEhttp://[hostname]/todo/api/v1.0/tasks/[task_id]删除任务

Flask-RESTful 提供了一个 Resource 基础类,它能够定义一个给定 URL 的一个或者多个 HTTP 方法

例如,定义一个可以使用 HTTP 的 GET, PUT 以及 DELETE 方法的 User 资源

基本示例

使用Flask-Restful,那么定义视图函数的时候,就要继承自flask_restful.Resource类,然后再根据当前请求的method来定义相应的方法

from flask import Flask
from flask_restful import Api, Resource

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

class UserAPI(Resource):
    def get(self, id):
		return {"data": "OK"}

api.add_resource(UserAPI, '/users/<int:id>', endpoint = 'user')

如果是和蓝图进行结合使用,那么应该Api不在使用flask生成的app对象,而应该是蓝图对象

# 1. 蓝图对象
user_blueprint = Blueprint('user', __name__, url_prefix='/user')

# 2. 初始化蓝图对象Api
user_api = Api(user_blueprint)

class UserAPI(Resource):
    def get(self, id):
        return {"data": "OK"}
      
# 3. 类视图路由注册
user_api.add_resource(UserAPI, '/users/<int:id>', endpoint = 'user')

Flask应用注册蓝图对象还是必不可少的

app.register_blueprint(user_blueprint)

路由映射

Flask-rest框架对应的视图通过add_resource进行路由映射

def add_resource(self, resource, *urls, **kwargs):
	if self.app is not None:
        self._register_view(self.app, resource, *urls, **kwargs)
    else:
        self.resources.append((resource, urls, kwargs))

比如

api.add_resource(Index, '/<int:id>', endpoint="index")

请求验证

在之前编写的代码中,对于用户提交参数的验证是非常麻烦的,如果提交数据过多,那么会造成大量的if判断,如下所示

def update_task(task_id):
    task = filter(lambda t: t['id'] == task_id, tasks)
    if len(task) == 0:
        abort(404)
    if not request.json:
        abort(400)
    if 'title' in request.json and type(request.json['title']) != unicode:
        abort(400)
    if 'description' in request.json and type(request.json['description']) is not unicode:
        abort(400)
    if 'done' in request.json and type(request.json['done']) is not bool:
        abort(400)

Flask-RESTful 提供了一个更好的方式来处理数据验证,它叫做 RequestParser 类。这个类工作方式类似命令行解析工具 argparse

parser = reqparse.RequestParser()
parser.add_argument('username',type=str,help='请输入用户名')
args = parser.parse_args()

首先,对于每一个资源需要定义参数以及怎样验证它们

from flask_restful import Resource, reqparse

class Index(Resource): # 视图类
    def __init__(self): # 重写init方法
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('account', type = str, required = True, help = '需要提供一个账号', location = 'json')
        self.reqparse.add_argument('password', type = str, default = "123456", location = 'json')
        super(Index, self).__init__()

在 Index 视图中,使用POST 方法接收参数

参数id是必须的,因此定义一个缺少id的错误信息,当客户端缺少这个参数的时候,Flask-RESTful 将会把这个错误信息作为响应发送给客户端

default字段是可选的,当缺少这个字段的时候,默认的字符串123456将会被使用

RequestParser 类默认情况下在 request.values 中查找参数,因此 location 可选参数被设置以表明请求参数类型为 request.json 格式的

请求获取

如果是正常的json数据提交,那么数据可以正常拿取

request.json

如果是通过官方文档建议的获取方式过滤参数,那么在正确传递参数的情况下,可以这样获取

args = self.reqparse.parse_args()
args.get("account") # 和字典类似的数据对象
'''
<class 'flask_restful.reqparse.Namespace'>

['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
'''

add_argument可以指定这个字段的名字,这个字段的数据类型等。以下是这个方法的一些参数的详细讲解

  1. default:默认值,如果这个参数没有值,那么将使用这个参数指定的值。
  2. required:是否必须。默认为False,如果设置为True,那么这个参数就必须提交上来。
  3. type:这个参数的数据类型,如果指定,那么将使用指定的数据类型来强制转换提交上来的值。
  4. choices:选项。提交上来的值只有满足这个选项中的值才符合验证通过,否则验证不通过。
  5. help:错误信息。如果验证失败后,将会使用这个参数指定的值作为错误信息。
  6. trim:是否要去掉前后的空格

生成响应

Flask-RESTful 如果返回的是字典格式会自动地处理转换成 JSON 数据格式,原来设计的 REST 服务器使用 Flask 的 jsonify 函数来生成响应

return jsonify( { 'code': 200} )

现在!

return {"code": 200}

序列化

对于一个视图函数,你可以指定好一些字段用于返回json格式数据,进行序列化

以后可以使用ORM模型或者自定义的模型的时候,他会自动的获取模型中的相应的字段,生成json数据,然后再返回给客户端

比如只包含包如下字段的模型类设计序列化字段

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), index=True, nullable=False)
resource_fields = {
    'id': fields.Integer, # 序列化id字段
    'name': fields.String, # 序列化name字段
}
  • 第一种序列化使用装饰器

那么使用这个序列化字段进行接口数据返回

@marshal_with(resource_fields, envelope="users")
def get(self):
    return Users.query.all()

envelope指定了一个可选的关键字参数来包装结果输出,这个地方经常写data,代表json接口返回的整体数据

{
  	users: [...]
}
  • 第二种序列化使用marshal
return marshal(data, fields, envelope=None)
'''
data: 模型数据
fields: 序列化映射字典
envelope: 包裹数据的KEY
'''
序列化默认值

在返回一些字段的时候,有时候可能没有值,那么这时候可以在指定fields的时候给定一个默认值,示例代码如下:

resource_fields = {
    'name': fields.String(default="blank")
}
重命名属性

很多时候你面向公众的字段名称是不同于内部的属性名

使用 attribute可以配置这种映射。比如现在想要返回user.account中的值,但是在返回给外面的时候,想以name作为key返回回去,那么可以这样写:

resource_fields = {
    'name': fields.String(attribute='account')
}
复杂序列化

https://flask-restful.readthedocs.io/en/latest/fields.html#list-field

class Follow(db.Model):
    __tablename__ = 'follows'

    id = db.Column(db.Integer, primary_key=True)
    idol = db.Column(db.Integer, db.ForeignKey("users.id"))  # 偶像
    fans = db.Column(db.Integer, db.ForeignKey("users.id"))  # 粉丝
    db.UniqueConstraint('idol', 'fans', name="follow_relation")

    def __repr__(self): return self.name


class Users(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), index=True, nullable=False)
    fans = db.relationship("Users", secondary="follows", backref=db.backref("idols", lazy="dynamic"),
                           lazy="dynamic",  # 由于是多对多,所以生成query对象可以继续查询
                           primaryjoin=(Follow.idol == id),  # 左侧,用于获取 我的粉丝
                           secondaryjoin=(Follow.fans == id)  # 右侧,用于获取 我的偶像
                           )

比如对之前例子中的多对多关注进行序列化展示,在主表中的fans字段是一个用户的粉丝们,那么序列化返回粉丝的json字典将定义如下

users_resource_fields = {
    'id': fields.Integer,
    'name': fields.String,
}
resource_fields = {
    'id': fields.Integer,
    'name': fields.String,
    'fans': fields.List(fields.Nested(users_resource_fields)),
}

全部的接口像这样

class Index(Resource):
    users_resource_fields = {
        'id': fields.Integer,
        'name': fields.String,
    }
    resource_fields = {
        'id': fields.Integer,
        'name': fields.String,
        'fans': fields.List(
            fields.Nested(users_resource_fields)
        ),
    }
    
    def get(self):
        # return {"code": 200}
        # return Users.query.first()
        data = Users.query.all()
        return marshal(data, self.resource_fields, envelope='data')
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`Flask-RESTful` 是 Flask 的一个扩展,它使创建 RESTful API 变得更加容易。使用 Flask-RESTful,你可以使用 Python 类来定义资源(Resource),并使用 Flask 的路由系统来将 URL 映射到这些资源上。 Flask-RESTful 提供了一组类和方法来处理 HTTP 请求和响应,例如 `Resource`、`Api`、`reqparse` 等。其中,`Resource` 类表示一个 RESTful 资源,它封装了 HTTP 请求和响应的处理逻辑。`Api` 类表示整个 RESTful API,它可以将多个资源组合在一起,并将它们映射到 URL 上。`reqparse` 类用于解析和验证 HTTP 请求参数。 下面是一个简单的使用 Flask-RESTful 的示例: ``` from flask import Flask from flask_restful import Api, Resource, reqparse app = Flask(__name__) api = Api(app) class HelloWorld(Resource): def get(self): return {'hello': 'world'} api.add_resource(HelloWorld, '/') if __name__ == '__main__': app.run(debug=True) ``` 在上面的示例中,`HelloWorld` 类继承自 `Resource` 类,表示一个 RESTful 资源。`get()` 方法表示处理 HTTP GET 请求的逻辑,它返回一个 JSON 响应。`api.add_resource()` 方法将 `HelloWorld` 资源映射到根 URL 上。当用户访问根 URL 时,Flask-RESTful 将自动调用 `HelloWorld` 资源的 `get()` 方法,并返回 JSON 响应。 Flask-RESTful 还支持其他 HTTP 方法,例如 POST、PUT、DELETE 等。你可以根据实际需求定义不同的资源和方法,以创建一个完整的 RESTful API。 总之,Flask-RESTful 是一个非常方便的 Flask 扩展,可以帮助你轻松地创建 RESTful API,从而提供 Web 服务和数据接口。它提供了一组类和方法,使 HTTP 请求和响应的处理变得更加简单和易于维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李恩泽的技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值