restful
restful风格是对于传输风格的规范化,更加整齐干净。
安装
首先我们需要安装flask-restful
pip3 install flask-restful
注册
在ext文件夹中声明api
restful_api=Api()
将flask的app放入到api的.init方法中进行实例化
app=Flask(__name__)
restful_api.init_app(app)
使用
之前我们使用flask本身的blueprint蓝图进行细致分化,引用了flask-restful后,使用的就是定义类方法。
class SpiderResource(Resource):
def get(self):
res = requests.get(
'https://proxy.pixivel.moe/c/540x540_70/img-master/img/2023/02/20/00/15/59/105538757_p0_master1200.jpg')
dirs = 'C:\\Users\\Administrator\\Desktop\\物体'
response = make_response(res.content)
response.headers['Content-Type']='image/jpg'
return send_file(io.BytesIO(res.content),'image/jpg')
def post(self):
pass
我们每次新声明resource都需要注册起来,后面写上你的访问路径。
resource_api.add_resouces(SpiderResource,'/spider')
json格式
当我们想要使用application/json格式传输一个自定义对象,他会无法进行dump,所以我们在原本的flask中使用了新声明的方式。
我们在model类中创建一个定义方法
def blog_dict(self):
return {
'id': self.id,
'user_id': self.user_id,
'title': self.title,
'description': self.description,
'content': self.content,
'create_time': self.create_time.strftime("%Y-%m-%d"),
'status': self.status,
'gallery': self.gallery,
'comment_amount': Comment.query.filter(Comment.b_id == self.id).count(),
'type':self.type.t_name
}
然后利用python的simple expression将blogs里的每一个取出来使用自己的方法,然后再次保存。
blogs = Blog.query.filter(Blog.user_id == 1).all()
jsonify(blogs=[e.blog_dict() for e in blogs],
那在restful中,我们可以使用它的方法进行实现,首先我们创建一个自定义对象的dict
blog_fields={
'id': fields.Integer,
'user_id': fields.Integer,
'title': fields.String,
'description': fields.String,
'content':fields.String,
'create_time': fields.DateTime('%Y-%m-%d'),
'status': fields.Integer,
'gallery': fields.String,
# 'comment_amount': Comment.query.filter(Comment.b_id == self.id).count(),
# 'type':self.type.t_name
}
然后在你要传输的方法上写上注解marshal_with(dict)
class HomeResource(Resource):
@marshal_with(blog_fields)
def get(self, limit):
uid = session.get('uid')
count = 0
pageUtil = PageUtil(limit, 2)
if uid is not None:
这样就可以传输json值了。
路径传参
https:/localhost:8080/user/1这个意思就是访问id为1的用户,那我们如何这样访问呢。
class UserSimpleApi(Resource):
def get(self):
pass
restful_api.add_resource(UserSimpleApi,'/user/<int:id>',endpoint='get_user')
大家可以看到,更改的地方就是在本身设置url的地方增加一个参数,就可以了。
add_resource还有一个endpoint的参数,跟flask的一样,填上后,用来改变url rule。
reqparse
flask-restful为我们提供了attribute的检查,我们可以使用。
创建一个parse对象
parse=reqparse.RequestParser(bundle)
利用这个parse对象添加argument
parse.add_arrgument('username',type=str)
parse.add_arrgument('password',type=str,required=True,help='必须输入密码')
add_argument
1.type:规定传参类型
2.required=bool :规定必须拥有
3.help:如果拥有required后,他没有填写可以用help进行提示
4.location:必须是post请求
5.action:将参数规定为
剩下具体的可以看源码
获取所有值使用
args=parse..parse_args()
user=args.get('username')
password=args.get('password')
对于判断里面有required的,没有填就会返回错误,统一封装到叫message的json数据里返回。
{
message{
'username':'error username'
}
}
bundle_erros
但是他只会爆出来第一个错误,那如何让他把错误都显示出来呢,就需要在声明parse的时候参数里面加上bundle_errors=True
parser = reqparse.RequestParser(bundle_errors=True)
自定义fields
必须继承 raw
必须实现format函数
class IsDelete(fields.Raw):
def format(self, value):
pass
# 这里使用attribute将forms内容传入自定义fields
user_fields={
'id':fields.string,
'is_delete':IsDelete(attribute=isDelete)
}
复杂数据输出
上面我们只是演示了普通数据的传输,假如我们对象里面还有一个新的对象,或者一个新的对象列表,那他是无法进行遍历的,这个时候我们应该怎么办,这里有两个方法。
fields.Nested(fiedls)
使用fields.Nested(field)可以完成一对一的操作。在方法体上面你要写上注解**@marshal_with(fleds)**
user_fields = {
'id': fields.Integer,
}
type_fields={
't_id':fields.Integer,
}
blog_fields = {
'type':fields.Nested(type_fields),
'writer':fields.Nested(user_fields)
}
一对多的写法:
在外面加上fields.List()
comment_fields={
'id': fields.Integer,
'u_id': fields.Integer,
'b_id': fields.Integer,
'comment': fields.String,
'write_time': fields.DateTime(),
}
# 意思是将他转换为comment_fields类型的列表
blog_fields = {
'id': fields.Integer,
'comments':fields.List(fields.Nested(comment_fields))
}
marshal()
这是一种不使用装饰器的区别,你不需要再写注解,但是你的数据段里面需要加上marshal自己更改。
第一个参数是你的自定义类,第二个参数是你要转换的fields。
blog_fields = {
'id': fields.Integer,
'user_id': fields.Integer,
'title': fields.String,
'description': fields.String,
'content': fields.String,
'create_time': fields.DateTime('iso8601'),
'status': fields.Integer,
'gallery': fields.String,
'comment_amount': fields.String,
'url': fields.Url(endpoint='simple_blog', absolute=True),
'type':fields.Nested(type_fields),
'writer':fields.Nested(user_fields)
}
def get(self){
data = {
'blogs': marshal(blogs, blog_fields)
}
return data;
}
这些就是restful的正常使用了。