- 首先,安装一个postman来测试备用,这玩意非常的难在官方下载,其他非官方渠道往往都不稳定我就不贴连接了免得失效了也是白弄,自己找自己下看运气。
- 然后是flask-restful
flask-restful的文档传送门 - 安装
pip install flask-restful
4.使用API首先在扩展中导入,exts文件下的init.py中,因为数据库和API配合使用,而前端都是常用的我就一起都放这里了
#数据库
from flask_sqlalchemy import SQLAlchemy
db =SQLAlchemy()
#前段框架
from flask_bootstrap import Bootstrap
bootstrap=Bootstrap()
#api扩展
from flask_restful import Api
api=Api()
5.在工厂函数中绑定,一般我会在apps/init.py中构建这个函数
#配置文件导入
from setting import Config
#数据库
from exts import db # 这个DB是SQLAlchemy 制造的
#蓝图
from apps.view import user_bp # 引入蓝图的声明
#前段框架
from exts import bootstrap #
#表单
from flask_wtf import CSRFProtect
#Api导入
from exts import api
def create_app(app):
app.config.from_object(Config)#环境配置
app.register_blueprint(user_bp) # 视图蓝图注册
db.init_app(app) # 这个是 SQLAlchemy 提供的绑定方法
bootstrap.init_app(app=app) # 全段框架绑定
csrf = CSRFProtect(app=app) # 全局令牌绑定
api.init_app(app=app) #api绑定
return app
- 在apps/views.py这个视图文件里边写api功能
#引入api扩展
from exts import api
#定义API类视图
from flask_restful import Resource #引入这个特殊类在类定义的时候继承
#定义api功能类,记得要继承Resource
class UserResource(Resource):
# get 请求
def get(self):
return {'msg':'GETgaoke'}
# post 请求
def post(self):
return {'msg':'POSTgaoke'}
# put 请求
def put(self):
return {'msg':'PUTgaoke'}
# delete 请求
def delete(self):
return {'msg':'DELTETgaoke'}
#最后,务必要将定义的类通过add_resource方法添加入api
api.add_resource(UserResource,'/user')
这里注意这个api.add_resource(UserResource,'/user')
写在视图文件里在每个功能类最后执行添加过程,如果把这个玩意弄到工厂函数中去添加则无效,简单说就写这里就像路由装饰器它写前面,这个功能和路由装饰器类似,他写后面.
上面提供了四个方法,GET方法浏览器直接访问就可以,其他方法需要借助POSTMAN测试,这里注意,如果开启了wtf-form表单则并开启了全局token验证,则api的 get意外三个方法都会显示 token丢失。我下面记录一个关闭验证的方法,就是在配置文件中加一句WTF_CSRF_CHECK_DEFAULT = False #这个关闭所有表单的验证
,配置文件如下:
class Config(object):
DEBUG=1
SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:ga****622@47.1*5.7*.1**:3306/ckck01'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = 'sdfasdf2312asdf' #session的随机种子也是WRF-Form的令牌种子
EVN='development'
WTF_CSRF_CHECK_DEFAULT = False #这个关闭所有表单的验证
至此,最简API搭建出来,下面配合数据库:
~~~~~~~~fields的内容,输出格式化
这里的逻辑是先构建一个输出格式字典,然后在方法前添加一个装饰器把字典传装饰器里
下面这个是输出格式字典,这个格式有几个参数 attribute=‘name’ default=‘默认值’
from flask_restful import fields #输出格式化的类型
out_format= {
'id':fields.Integer,
'username':fields.String,
'password':fields.String,
'udatetime':fields.DateTime
}
这个格式有几个参数 attribute=‘name’
default='默认值'
他俩的意思一个是隐藏数据库字段名字:如下列子中前段看到和拿到的密码是pwd
的值而我们后端数据库中字段名字是password
,如果没有attribute参数则必须把数据库字段暴露给前端。
另一个是没取到值就默认输出的内容。
out_format= {
'id':fields.Integer,
'name':fields.String(attribute='username', default='默认值'),
'pwd':fields.String (attribute='password'),
'udatetime':fields.DateTime
}
下面是装饰器
from flask_restful import marshal_with #引入这个装饰器用来包装输出格式
class UserResource(Resource):
# get 请求
@marshal_with(out_format)####把上面的构建的字典传进来
def get(self):
u_api=Userapi.query.all()#查询数据库,获取数据集合
return u_api
至此,输出都会按照定义好的格式进行输出。
传参—get方法之尖括号
class UserSimResource(Resource): #注意1:类要继承
def get(self,id): #注意2:接收传参
return {'msg':'haha,get:%s'%str(id)}
api.add_resource(UserSimResource,'/user/<int:id>')#注意3:路由绑定以及传参格式设定
带上数据库和格式化输出则下面这样~
############## 单个查询
class UserSimResource(Resource):
@marshal_with(out_format)
def get(self,id):
xx=Userapi.query.get(id)
return xx
def put(self,id):
pass
api.add_resource(UserSimResource,'/user/<int:id>')
关于~ endpoint=
的使用,它仅仅是在路由上给这个路由起个别名的意思比如下面这个路由,本来叫UserSimResource
加了endpoint
后就叫user1
,具体用法和FLAKS视图差不多都是用url_for('user1')
来找路由
api.add_resource(UserSimResource,'/user/<int:id>',endpoint='user1')
传参与验证reqparse
这个传参验证逻辑是
- 建立一个解析对象
parser1= reqparse.RequestParser()
- 把要盯梢的名字添加进入解析对象,同时还可以加入验证和报错消息
parser1.add_argument('password',required=True,help='必须输入值')
- 在具体的请求中获取带数据的对象
args=parser1.parse_args()
- 取出具体名字的值
username=args.get('username')
from flask_restful import reqparse #传参验证总司令
parser1= reqparse.RequestParser() #解析对象
parser1.add_argument('username',type=str) #把要获取的名字加进来进行声明,逗号后面基本都是验证
parser1.add_argument('password',required=True,help='必须输入值') #required=True意思是必须传值,否则报错,报错内容由help=‘内容’来负责
#parser1.add_argument('password',type=int) #这个type可以指定类型
#
class UserResource(Resource):
# get 请求
@marshal_with(out_format)
def get(self):
u_api=Userapi.query.all()
return u_api
# post 请求
def post(self):
args=parser1.parse_args() #获取数据
username=args.get('username')
password=args.get('password')
user = Userapi()
user.username=username
user.password=password
db.session.add(user)
db.session.commit()
return {'username':username,'password':password}
关于postman模拟POST请求
因为POST请求在Body里边所以记得按照下面进行选择,就可以传语句体的POST
此时,如果用拼接方式POST传值也是可以的,都能取到,只是路由上会拼上一堆东西很扎眼
如果,不允许拼接式POST传值则要:location = ['form']
表示只允许表单POST方式提交
parser1= reqparse.RequestParser() #解析对象
parser1.add_argument('username',type=str ,location = ['form']) #把要获取的名字加进来
#进行声明,逗号后面基本都是验证,location = ['form']则不让拼接传值
这个location参数里边是列表,写什么方式什么方式可以进来比如:
parser1.add_argument('username',type=str ,location = ['form',‘args’])
就可以POST和GET ,其他的还有‘headers’,'cookies'
正则方法验证:
from flask_restful import inputs
parser1.add_argument('phone',type=inputs.regex(r'^1[356789]\d{9$}'))
#这个type可以指定类型,inputs.regex()是正则方法验证
#这个正则是验证手机号
列表式传入参数
如果要获取参数内部有,action='append')
parser1.add_argument('username',action='append')
则‘username’
他会以列表的形式接受多个参数:
类似 username=[‘曹操’,‘老大’,‘枭雄’] 这么个意思
接收文件(或者图片)的方式
- 引入类型
- 加入监听,指定类型并验证类型
from werkzeug.datastructures import FileStorage
parser1.add_argument('icon',type=FileStorage,location=['files'])
class UserResource(Resource):
def post(self):
args=parser1.parse_args()
icon = args.get('icon')
if icon :#icon如果有可以直接保存
icon.save('./static/%s'%icon.filename)
#icon.filename可以拿到文件名,怕重名可以在名字里边加随机数字
下面是比较标准的保存路径写法
upload_path=os.path.join(Config.UPLOAD_ICON_DIR,icon.filename)#标准化的保存路径写法
icon.save(upload_path)
保存路径到数据库
user = Userapi()
if icon :
user.icon = os.path.join('upload',icon.filename)#保存到数据库,这里注意他的路径因为是基于FLASK调用的所以是在STATIC下的相对路径,上面那个是绝对路径
错误消息
bundle_errors=True
这个参数默认是FALSE只报第一个错误,如果为True则报错的时候会一次性把所有错误报出来
parser1= reqparse.RequestParser(bundle_errors=True)
#解析对象