Flask之Restful(flask框架)

网友投稿 476 2022-08-31


Flask之Restful(flask框架)

restful api是用于前端和后台进行通信的一套规范。使用这个规范可以让前后端开发变得更加轻松。

协议

采用获取文章列表,应该使用/articles/, 而不应该使用/get_article/

HTTP请求方法

GET: 从服务器上获取资源  (常用)

POST:在服务器上新创建一个资源  (常用)

PUT:在服务器上更新资源。(客户端提供所有改变后的数据)

PATCH:在服务器上更新资源。(客户端只提供需要改变的属性)

DELETE: 从服务器上删除资源

状态码

状态码

原生描述

描述

200

OK

服务器成功响应客户端的请求

400

INVALID REQUEST

用户发出的请求有错误,服务器没有进行新建或修改数据的操作

401

Unauthorized

用户没有权限访问这个请求

403

Forbidden

因为某些原因禁止访问这个请求

404

NOT FOUND

用户发送的请求的url不存在

406

NOT Accept

用户请求不被服务器接收(比如服务器期望客户端发送某个字段,但没有发送)

500

Internal server error

服务器内部错误,比如出现了bug


安装flask-restful插件

pip install flask-restful

定义Restful视图

如果使用flask-restful,那么定义视图函数的时候,就要继承自flask_restful.Resource类,然后再根据当前请求的method来定义相应的方法。比如期望客户端使用get方法发送请求,那么就定义一个get方法,期望客户端使用post方法发送请求,就定义一个post方法。类似于MethodView.

url中也可以传递参数:

url也可以是多个:

参数验证

Flask-Restful插件提供了类似WTForm来验证提交的数据是否合法的包,叫做reqparse。以下是基本用法

parser = reqparse.RequestParser() parser.add_argument('username', type=str, required=True, help='用户名验证错误') args = parser.parse_args()

add_argument可以指定这个字段的名字,这个字段的数据类型等

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

其中的type,可以使用python自带的一些数据类型,也可以使用flask_restful.inputs下的一些特定的数据类型来强制转换。比如一些常用的:

url:会判断这个参数的值是否是一个url,如果不是,那么就会抛出异常。regex:正则表达式。date:将这个字符串转换为datetime.date数据类型。如果转换不成功,则会抛出一个异常。

因为username字段添加了参数required=True,为必填项,因此如果客户端不传此字段,就会提示错误,这个错误提示就是我们自定的help--->"用户名验证错误"

...from flask_restful import Api, Resource, reqparse, inputsapp = Flask(__name__)app.config.from_object(config)api = Api(app)class RegisterView(Resource): def post(self): parser = reqparse.RequestParser() parser.add_argument('username', type=str, required=True, help='用户名字段验证错误') parser.add_argument('birthday', type=inputs.date, required=True, help='生日字段验证错误') parser.add_argument('gender', type=str, choices=('male', 'female'), help='性别字段验证错误') parser.add_argument('money', type=int, trim=True, default=0, help='金额字段验证错误') parser.add_argument('phone', type=inputs.regex(r'1[3458]\d{9}'), help='手机字段验证错误') parser.add_argument('blog', type=inputs.url, help='博客地址字段验证错误') args = parser.parse_args() print(args) return 'success'api.add_resource(RegisterView, '/register/', endpoint='register')...

Flask-Restful标准化返回参数

对于一个视图函数,我们可以指定好一些参数用于返回,在规范中要求:即使这个参数没有值也应该返回,返回一个None回去

...from flask_restful import Api, Resource, fields, marshal_withapi = Api(app)class ArticleView(Resource): resource_field = { #先定义好返回哪些参数 'name': fields.String, #参数的数据类型 'age': fields.String, 'school': fields.String } @marshal_with(resource_field) #利用marshal_with装饰器传入定义好的返回参数 def get(self): return {} 就算这里返回个空字典,也会把定义好的参数返回api.add_resource(ArticleView, '/article/', endpoint='article')

...class ArticleView(Resource): resource_field = { 'name': fields.String, 'age': fields.String, 'school': fields.String } @marshal_with(resource_field) def get(self): return {'name': 'heboan', 'age': 18}...

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

class ProfileView(Resource): resource_fields = { 'username': fields.String, 'age': fields.Integer, 'school': fields.String } @marshal_with(resource_fields) def get(self,user_id): user = User.query.get(user_id) return user

在get方法中,返回user的时候,flask_restful会自动的读取user模型上的username, age以及school属性。组装成一个json格式的字符串返回给客户端

重名属性

如果我们想把面向公众的字段名称不用与内部的属性名。使用attribute可以配置这种属性,比如现在想要返回user.school中的值,但是在返回给外面的时候,想以education返回回去,那么可以这样写

resource_fields = { 'education': fields.String(attribute='school')}

默认值

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

resource_fields = { 'age': fields.Integer(default=18)}

复杂的结构

有时候想要在返回的数据格式中,形成比较复杂的结构。那么可以使用一些特殊的字段来实现。比如要在一个字段中放置一个列表,那么可以使用fields.List,比如在一个字段下面又是一个字典,那么可以使用fields.Nested。以下将讲解下复杂结构的用法:

定义数据库结构:

user表,article表,tag表, 因为article与tag是多对多的关系,因此需要一个中间表来关联article_tag

from exts import dbclass User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(50), nullable=False)class Article(db.Model): __tablename__ = 'article' id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.String(50), nullable=False) content = db.Column(db.Text, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) author = db.relationship('User', backref='articles') tags = db.relationship('Tag', secondary='article_tag')class Tag(db.Model): __tablename__ = 'tag' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(50), nullable=False)article_tag = db.Table( 'article_tag', db.Column('article_id', db.Integer, db.ForeignKey('article.id')), db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')))models

添加测试数据

...from models import User, Article, Tag@app.route('/')def index(): user = User(username='heboan') tag_1 = Tag(name='Linux') tag_2 = Tag(name='Python') article = Article(title='python自动化运维', content='Life is short, I use python...') article.tags.append(tag_1) article.tags.append(tag_2) article.author = user db.session.add(article) db.session.commit() return '数据插入成功!'视图

当我们全部使用field.String

class ArticleView(Resource): resource_fields = { 'title':fields.String, 'content': fields.String, 'author':fields.String, 'tags':fields.String } @marshal_with(resource_fields) def get(self): article = db.session.query(Article).get(1) return articleapi.add_resource(ArticleView, '/article/', endpoint='article')

使用field.Nested、field.List

class ArticleView(Resource): resource_fields = { 'title':fields.String, 'content': fields.String, 'author':fields.Nested({ #字典里面嵌套字典使用field.Nested 'username': fields.String }), 'tags':fields.List(fields.Nested({ #tags是列表,使用field_List类型然后嵌套field.Nested 'id': fields.Integer, 'name': fields.String })) } @marshal_with(resource_fields) def get(self): article = db.session.query(Article).get(1) print(article.title) return articleapi.add_resource(ArticleView, '/article/', endpoint='article')

在蓝图使用使用Flask-Restfu

新建一个articles.py

from flask import Blueprintfrom flask_restful import Api, Resource, fields, marshal_withfrom exts import dbfrom models import Articlearticle_bp = Blueprint('article', __name__, url_prefix='/article')api = Api(article_bp) #这里使用article_bp了class ArticleView(Resource): resource_fields = { 'title':fields.String, 'content': fields.String, 'author':fields.Nested({ 'username': fields.String }), 'tags':fields.List(fields.Nested({ 'id': fields.Integer, 'name': fields.String })) } @marshal_with(resource_fields) def get(self): article = db.session.query(Article).get(1) print(article.title) return articleapi.add_resource(ArticleView, '/1/', endpoint='article')

主程序注册此蓝图

from article import article_bp...app.register_blueprint(article_bp)

Flask-Restful渲染模板

class HelloView(Resource): def get(self): return render_template('hello.html')api.add_resource(HelloView, '/hello/', endpoint='hello')

可以发现这样渲染出来的页面并不是我们想要的。要想使用Flask-Restful渲染页面还需要定义一个out_html函数

@api.representation('text/html')def out_html(data, code, headers): resp = make_response(data) return resp class HelloView(Resource): def get(self): return render_template('hello.html') api.add_resource(HelloView, '/hello/', endpoint='hello')


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:ORM之SQLAlchemy
下一篇:pycharm之激活(pycharm永久激活(含激活码))
相关文章

 发表评论

暂时没有评论,来抢沙发吧~