Python3 - 初探 Flask-Restful
Posted 韩俊强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python3 - 初探 Flask-Restful相关的知识,希望对你有一定的参考价值。
文章目录
1.什么是RESTful架构:
(1)每一个URI代表一种资源;
(2)客户端和服务器之间, 传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词(GET, POST, PUT, DELETE, [PATCH]), 对服务器资源进行操作, 实现"表现层状态转化"。
REST(Representational State Transfer)是一种架构风格,表述了网络中客户端于服务端的一种交互,REST本身是不实用的,关键的是如何设计它。REST架构就是为了HTTP协议设计的。RESTful web services的核心概念是管理资源。资源是由URIs来表示,客户端使用HTTP当中的’POST,GET, PUT, DELETE’等方法发送请求到服务器,改变相应的资源状态。
2.Postman
用来模拟客户端请求
3.前后端分离:
前端: app, 小程序, pc页面
后端: 没有页面, mtv: 模型模板视图, 去掉t模板
mv: 模型 视图
模型的使用: 跟原来的用法是相同的
视图: api构建视图
4. api构建视图
1. pip install flask-restful
2. 创建api对象
api = Api(app=app)
api = Api(app=蓝图对象)
3.定义类视图:
from flask_restful import Resource
class xxxApi(Resource):
def get(self):
pass
def post(self):
pass
def put(self):
pass
def delete(self):
pass
4.绑定
api.add.resource(xxxApi, '/user')
参照: http://www.pythondoc.com/Flask-RESTful/quickstart.html
https://flask-restful.readthedocs.io/en/latest
5.路由
原来:
@app.route('/user')
def user(): -----> 视图函数
...
return response对象
之前: 增加 修改 删除 查询 按钮动作 一起做
http://127.0.0.0.1:5000/user?id=1
http://127.0.0.0.1:5000/user/1
现在
restful: ---> api ---> 接口 ----> 资源 ----> url
class xxx(Resource): -----> 类视图
def get(self):
pass
...
http://127.0.0.0.1:5000/user 一个路由做四个事情
get
post
put
delete
增加 修改 删除 查询 是通过请求方式完成的
路径产生
api.add_resource(Resource的子类, '/user')
api.add_resource(Resource的子类, '/goods')
api.add_resource(Resource的子类, '/order')
endpoint:
http://127.0.0.0.1:5000/user/1
http://127.0.0.0.1:5000/user?id=1&page=4
6.进:
1.需要定义字典, 字典的格式就是给客户端看的格式
user_fields =
'id': fields.Integer,
'username': fields.String,
'password': fields.String(attribute='private_name', default='隐私不显示'), # 返回null
'udatetime': fields.DateTime(dt_format='rfc822'),
'your_phone': fields.String(attribute='phone', default='保密'), # attribute 指定返回给客户端的名字
'icon': fields.String
客户端能看到的是: id, username, your_name, icon, udatetime
默认key的名字就是跟model中的模型属性名一致, 如果不想让前端看到命名, 则可以修改, 但是必须结合attribute='模型字段名'
自定义fileds
1.必须继承Raw
2.重写方法:
def format(self):
return 结果
class IsDelete(fields.Raw):
def format(self, value):
print('------', value)
return '删除' if value else '未删除'
user_fields =
'isDelete': fields.Boolean(attribute='isdelete'),
'isDelete1': IsDelete(attribute='isdelete')
URI:
xxxList ----> 点击具体的一个获取详情 ----> 详情
定义两个user_fields,
user_fields_1 =
'id': fields.Integer,
'username': fields.String(default='匿名'),
'uri': fields.Url('single_user', absolute=True)
user_fields =
'id': fields.Integer,
'username': fields.String,
'password': fields.String(attribute='private_name', default='隐私不显示'),
'udatetime': fields.DateTime(dt_format='rfc822'),
'your_phone': fields.String(attribute='phone', default='保密'),
'icon': fields.String,
'isDelete': fields.Boolean(attribute='isdelete'),
'isDelete1': IsDelete(attribute='isdelete')
api.add_resource(UserSimpleResource, '/user/<int:id>', endpoint='single_user')
7.出:
return data
注意: data必须是符合json格式
'a': 10,
'b':[
'id':1,
'xxxlist':[
,
]
]
如果直接返回不能有自定义的对象User, Friend…
如果有这种对象, 需要: marshal(), marchal_with()帮助进行转换
输出目的如下:
"username": "harry",
"nums": 5,
"friends": [
"id": 1,
"username": "harry",
"password": "隐私不显示",
"udatetime": "Sat, 05 Mar 2022 17:24:43 -0000",
"your_phone": "保密",
"icon": null,
"isDelete": true,
"isDelete1": "删除"
,
"id": 1,
"username": "harry",
"password": "隐私不显示",
"udatetime": "Sat, 05 Mar 2022 17:24:43 -0000",
"your_phone": "保密",
"icon": null,
"isDelete": true,
"isDelete1": "删除"
,
"id": 1,
"username": "harry",
"password": "隐私不显示",
"udatetime": "Sat, 05 Mar 2022 17:24:43 -0000",
"your_phone": "保密",
"icon": null,
"isDelete": true,
"isDelete1": "删除"
]
user_friend_files =
'username': fields.String,
'nums': fields.Integer,
'friends': fields.List(fields.Nested(user_fields))
class UserFriendResource(Resource):
@marshal_with(user_friend_files)
def get(self, id):
friends = Friend.query.filter(Friend.uid==id).all()
user = User.query.get(id)
friend_list = []
for friend in friends:
u = User.query.get(friend.uid)
friend_list.append(u)
data =
'username': user.username,
'nums': len(friends),
'friends': friend_list
# 'friends': marshal(friend_list, user_fields)
return data
api.add_resource(UserFriendResource, '/friend/<int:id>', endpoint='user_friend')
总结: marshal 放在局部比较灵活, marshal_with
对整体控制比较好, 配合Nested
可以实现套fileds
1.marchel(对象, 对象的fields格式) # 对象的field说个是指字典的输出格式
2.marchal_with()作为装饰器修饰请求方法
@marshal_with(user_friend_files)
def get(self, id):
...
return data
函数需要参数, 参数就是最终数据输出的格式
参数: user+friend_fields, 类型是: dict类型
例如:
user_friend_files =
'username': fields.String,
'nums': fields.Integer,
'friends': fields.List(fields.Nested(user_fields))
fields.Nested(fields.String) ---> ['aa', 'bb', 'cc']
fields.Nested(user_fields) ----> user_fields是一个字典结果, 将里面的每一个对象转成
---->[user1, user2, user3]
8.跨域问题
跨域问题来源于javascript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题。
后端: 使用第三扩展 flask-cors
9.Token令牌
在 OAuth 协议中,token 是在输入了用户名和密码之后获取的,利用这个 token 你可以拥有查看或者操作相应的资源的权限。你有这些权限,是因为服务器知道你是谁(authentication)以后赋予你的,所以 token 这个东西,其实就是你的一个『代表』,或者说完全能代表你的『通行证』。从这个概念来说,『令牌』这个翻译,真的是非常的『信雅达』啊。
Flask 实现:
import jwt
import datetime
from jwt import exceptions
JWT_SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='
def create_token(payload, timeout=20):
"""
:param payload: 例如:'user_id':1,'username':'wupeiqi'用户信息
:param timeout: token的过期时间,默认20分钟
:return:
"""
headers =
'typ': 'jwt',
'alg': 'HS256'
payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
result = jwt.encode(payload=payload, key=JWT_SALT, algorithm="HS256", headers=headers).decode('utf-8')
return result
def parse_payload(token):
"""
对token进行和发行校验并获取payload
:param token:
:return:
"""
result = 'status': False, 'data': None, 'error': None
try:
verified_payload = jwt.decode(token, JWT_SALT, True)
result['status'] = True
result['data'] = verified_payload
except exceptions.ExpiredSignatureError:
result['error'] = 'token已失效'
except jwt.DecodeError:
result['error'] = 'token认证失败'
except jwt.InvalidTokenError:
result['error'] = '非法的token'
return result
以上是关于Python3 - 初探 Flask-Restful的主要内容,如果未能解决你的问题,请参考以下文章