Flask笔记:RESTful
RESTful是用于前台和后端进行通信的一种规范或者说一种风格,采用的是HTTP和HTTPS协议,数据传输的格式使用的都是JSON,而不是XML。通常,RESTful的URL中只有名词,没有动词,而且名词在复数的情况就应该使用其复数的形式。网上有专门讲解RESTful的详细教程,本文只是Flask中用于实现RESTful规范的插件Flask-RESTful的学习笔记,就不详细介绍RESTful了。 安装:pip install Flask-RESTful 使用场景:一般来说,如果URL是用于向前台返回json数据,就可以考虑使用这个RESTful插件了。 ? RESTful基础使用 RESTful的使用重点在视图类的定义,包括请求方法的定义,基础使用步骤如下,具体参见示例代码:
简单示例: from flask import Flask,url_for from flask_restful Api,Resource app = Flask(__name__) # 创建API对象 api = Api(app) class LoginView(Resource): 如果url中定义了参数,请求方法也需要定义对应的参数 如果add_resource中有url没有这个参数,就需要给这个参数设置一个默认值 def post(self,username='xiaowang'): 如果使用的是restful,返回值的类型就需要是json格式数据,即字典 return {username': xiaoming} 可以在url中指定参数,就和“app.route”中定义参数一样,也需要在对应请求方法里也定义这个参数 # add_resource定义url时,可以传入多个url,比如第二个url是没有传入参数的,这时候就需要在定义请求方法时将这个参数设置一个默认值,不然会报错 endpoint参数用于url_for函数反转,如果不指定endpoint参数,那么将使用视图类的名称的全小写作为endpoint api.add_resource(LoginView,/login/<username>/',1)">/login/login) 创建请求上下文,测试endpoint参数 with app.test_request_context(): 测试url:/login/ print(url_for()) 测试url:/login/<username>/ )) if __name__ == __main__: app.run() ? ? RESTful参数验证 对于请求中的form表单验证,RESTful也有实现对应的验证方法,即flask_restful.reqparse,在对应的请求方法中进行form表单数据验证的步骤如下,具体参见示例代码:
简单示例: def post(self): 创建解析对象 parser = reqparse.RequestParser() 获取form中的字段,并指定对应的验证方式 parser.add_argument(用户名验证错误!) parser.add_argument(password密码验证错误!) 开始解析并验证字段信息 返回结果args是一个字典,如:{'username': 'xiaozhi','password': '123456'} args = parser.parse_args() 如果验证失败则不会正常返回,而是返回关于验证失败的一个json数据,即字典数据,可打印查看具体信息和字典结构 print(args) 如果使用的是restful,返回值的类型就需要是json,即字典 } api.add_resource(LoginView,) : app.run() ? ? RESTful标准化返回值 标准化返回值,即对同一个视图类中的请求方法返回的json数据进行统一化和规范化,具体见示例代码:
简单示例(只列了两个关键文件,其他文件省略了): models.py from exts db User(db.Model): """user表,存储用户信息""" __tablename__ = user id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(50)) email = db.Column(db.String(50)) 中间表,存储article表和tag表的对应关系 article_tag_table = db.Table( article_tag,db.Column(article_idarticle.id'),1)">True),1)">tag_idtag.idTrue)) Article(db.Model): article表,存储文章信息articleTrue) title = db.Column(db.String(100)) content = db.Column(db.Text) author_id = db.Column(db.Integer,1)">user.id)) 文章对应的作者,是多对一的关系 author = db.relationship(Userarticles) 文章对应的标签,是多对多的关系 tags = db.relationship(Tagtags Tag(db.Model): tag表,存放文章的标签信息tagTrue) name = db.Column(db.String(50)) ? 主文件 Flask config db from models User,Article,Tag app = Flask( config文件中就定义了数据库连接的信息,一行代码:SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}?charset=utf8'.format(username='root',password='123456',host='127.0.0.1',port=3306,database='restful_demo') app.config.from_object(config) api = Api(app) exts文件中就两句代码:from flask_sqlalchemy import SQLAlchemy;db = SQLAlchemy() db.init_app(app) ArticleView(Resource): 定义字典信息,用作请求方法的标准返回值 resource_fields = { 字典key值会用作返回值字典的key值,并且如果没有在数据类型中指定attribute参数值,将会以这个key值在return对象中查找key值,当然,指定了attribute值,就会以attribute参数值去查找 字典的value值为flask_restful.fields中的数据类型 article_title': fields.String(attribute=title),1)">content: fields.String, 如果value值是另外一个对象,比如这里是author对象,就需要使用fields.Nested来获取该对象的详细信息 author: fields.Nested({ email: fields.String }),1)"> 如果value值为对象列表,比如这里是tag对象列表,则需要在fields.Nested外在加一层fields.List : fields.List(fields.Nested({ name 如果该key值没有找到对应信息,比如这里的read_count在article对象中就没有这个字段,可以使用default指定默认值 read_count': fields.Integer(default=0) } 必须使用flask_restful.marshal_with装饰器,并传入对应字典,此请求方法才会返回这个字典 @marshal_with(resource_fields) get(self,article_id): article = Article.query.get(article_id) return article api.add_resource(ArticleView,1)">/article/<article_id>/) @app.route(/ hello_world(): 往数据库表中添加信息,方便测试 user = User(username=123456.@qq.com) article = Article(title=pythonpython xxxxxxxx) article.author = user tag_flask = Tag(name=flask) tag_django = Tag(name=django) article.tags.append(tag_flask) article.tags.append(tag_django) db.session.add(article) db.session.commit() return Hello World!' : app.run() ? ? RESTful中使用蓝图 如果使用的是蓝图,也可以使用RESTful,只是实例化Api时用的不再是app对象了,而是蓝图对象,参见示例代码: 简单示例: Blueprint Article 创建蓝图对象,然后在app中注册蓝图即可:app.register_blueprint(article_bp) article_bp = Blueprint(__name__,url_prefix=/article 使用蓝图对象实例化Api,有多个蓝图对象就实例化多个Api即可。 api = Api(article_bp) pass 注意,由于蓝图中已经有url前缀了,这里的url不要添加多余的前缀了 api.add_resource(ArticleView,1)">/<article_id>/') ? ? RESTful返回HTML模板 虽然RESTful通常只是用来返回json数据,但是RESTful也可以返回其他类型的数据,比如HTML模板,参见示例代码:
简单示例: 这个装饰器表示Resource的子类中的请求方法如果返回的是指定的类型,这里是text/html类型,就会执行这个函数,并返回这个函数的返回值,并且这个返回值只能是Response对象 @api.representation(text/html output_html(data,code,headers): data表示text/html文件,code为状态码,headers为头部信息 如果访问http://127.0.0.1:5000/article/list/就不会返回list.html的内容了,而是返回hello字符串了 return make_response('hello') 如果访问http://127.0.0.1:5000/article/list/就会返回模板list.html中的内容了 make_response(data) ListView(Resource): get(self): return render_template(list.html) api.add_resource(ListView,1)">/list/list') ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |