前言

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

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

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

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

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

Flask-Restful

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

pip install flask-restful

请求回顾

方法 url示例 解释
GET http://[hostname]/todo/api/v1.0/tasks
http://[hostname]/todo/api/v1.0/tasks/[task_id]
检索任务列表
检索某个任务
POST http://[hostname]/todo/api/v1.0/tasks 创建新任务
PUT http://[hostname]/todo/api/v1.0/tasks/[task_id] 更新任务
DELETE http://[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, Resourceapp = 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, reqparseclass 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.nameclass 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')

Flask-Restful超详解、序列化相关推荐

  1. Android vector标签 PathData 画图超详解

    此文章来源于https://www.cnblogs.com/yuhanghzsd/p/5466846.html点击打开链接 Android vector标签 PathData 画图超详解 SVG是一种 ...

  2. Mybatis案例超详解

    Mybatis案例超详解 前言: 本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成熟点理解 ...

  3. python控制手机模拟器_Appium+python自动化之连接模拟器并启动淘宝APP(超详解)...

    简介 上一篇讲解完模拟器的安装.配置好以后,就好比我们手机已经买好,并且系统已经做好了,就差我们用数据线和电脑连接开始实战了,这篇宏哥就带着小伙伴们和童鞋们趁热打铁,讲解和分享一下如何连接模拟器(电脑 ...

  4. js打印三角形超详解

    js打印三角形超详解 j控制星星的总行数,i控制每行星星的打印个数 打印图形如下: (1) (2) //str=""用来存储星星// 理解步骤1:在一行输出6个星星如何操作,在循环 ...

  5. 线性规划之单纯形法【超详解+图解】-转载

    线性规划之单纯形法[超详解+图解] 目录 1.作用 2.线性规划的一般形式 5.1几何意义 5.2如何判断最优 5.3如何选择新的基变量 5.4如何选择被替换的基变量 5.5终止条件 标准型: 转化为 ...

  6. 【平衡小车制作】(七)串级PID调参及平衡成果展示(超详解)

      大家好,我是小政.本篇文章我将针对PID调参进行详细的讲解,让每位小伙伴能够对比例.积分.微分三个参数如何调节有更加清晰的理解. 一.调参步骤 确立机械中值 直立环(内环)--Kp极性.Kp大小. ...

  7. 蓝牙模块XY-MBD07A的介绍及使用方法(超详解)

    蓝牙模块XY-MBD07A的介绍及使用方法(超详解) 蓝牙XY-MBD07A是主从一体的蓝牙串口模块,简单的说,当蓝牙设备与蓝牙设备配对连接成功后,我们可以忽视蓝牙内部的通信协议,直接将将蓝牙当做串口 ...

  8. C/C++实现蛇形矩阵(超详解)【沈七】

    C/C++实现蛇形矩阵(超详解) 题目链接 题目描述 输入样例 题解部分 完整代码 完结散花 悄悄告诉你: 参考文章 萌新报道! 唤我沈七就行嘿嘿. 大一软件工程在读. 菜鸡蒟蒻想在博客中记录一些算法 ...

  9. [C++ 系列] 90. 超详解C++思维导图

    这段时间针对 C++ 的学习到了一个收尾的阶段.目前所涉及到了 C++ 基础语法.大小知识点的学习.当然语言学习绝对离不开实战项目的练手,网络优质资源以及各类经典丛书也是 C++ 学习的巨大宝库.在此 ...

  10. 【平衡小车制作】(一)硬件原理图讲解(超详解)

      大家好,我是小政.之后的一系列文章我将介绍我玩平衡小车的过程以及遇到的一些问题,将这些内容记录下来分享给大家,也让大家少走一些弯路.接下来我将从硬件框架选择.软件编程.PID算法.PID调参.蓝牙 ...

最新文章

  1. androidinclude作用
  2. 不重启JVM,替换掉已经加载的类,偷天换日?
  3. 【Luogu】P3224永无乡(splay)
  4. 编码方式 / ASCII、UNICODE、UTF-8、ANSI
  5. JavaFX 中 FX 一词的由来
  6. 摘:常用函数(包括:宽字符函数、普通C函数 )
  7. 阿里云宣布与Facebook达成合作 让AI开发更简单
  8. C++中数组、链表list、容器map/vector的区别
  9. Vue cli 入门补充
  10. java ts视频文件合并
  11. 百度、腾讯和阿里内部的级别和薪资待遇是什么样的?
  12. python课后练习(高琪400集第一季.第五章)
  13. CentOS安装onlyoffice
  14. Network网络诊断工具for windows
  15. 今日头条图片爬取和下载
  16. 支付宝、微信(pc+h5)支付
  17. Oracle如何快速、大量的插入数据
  18. visdom image显示图像(四)
  19. html中图片上下左右留白,vertical-align垂直居中( 消除html中图片下边缘留白 )
  20. 怎样用两部手机同时登陆一个QQ(两部手机同时在线)

热门文章

  1. objection 改源码解决 app的双进程保护 和 双进程保护原理 frida.core.RPCException: Error: expected a pointer
  2. 欢迎加入Cocos引擎中文官网官方QQ群!
  3. 潜水员(二维费用的背包问题)
  4. 【C语言编程】递归求勒让德多项式
  5. c语言编译器自带宏定义,C/C++中内置的宏定义
  6. 电脑、手机和iPad通过VNC Viewer连接树莓派4
  7. 联想 23 亿美元收购 IBM x86 服务器业务
  8. 非酋用计算机,《神武4》电脑版:洗宠100次必变异 再也不用流非酋泪
  9. 2019ICPC南京网络赛E题 K Sum
  10. nwchem (ROCM版)编译 -最终目标