本文共 4810 字,大约阅读时间需要 16 分钟。
在 这篇文章中,介绍了基于原生 CRUD 将查询结果转为 json 格式的方法。本篇接着介绍使用 Flask-SqlAlchemy 时,如何将查询结果转换为 json 格式。过程是先将查询的结果转为 dict/list,然后将 dict/list 转为 json,dict/list 转 json 是 Python 内置的功能,所以关键在如何将 Python 对象转换为 dict/list。
如果不使用第三方模块,需要手工编写代码来处理映射关系。假设在 MySQL 数据库中有一个 user 表,结构如下:
from flask import Flask, jsonifyfrom flask_sqlalchemy import SQLAlchemyimport osfrom collections import OrderedDictapp = Flask(__name__)# app.configurationsapp.config['SECURITY_KEY'] = 'you will never guess'app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DB_URI']app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Trueapp.config['JSON_SORT_KEYS'] = Falsedb = SQLAlchemy(app)class User(db.Model): __tablename__ = 'user' USER_ID = db.Column(db.Integer, primary_key=True) USERNAME = db.Column(db.String(20)) CREATED_BY = db.Column(db.String(20)) CREATED_DATE = db.Column(db.Date)def user_to_dict(user): return OrderedDict( USER_ID = user.USER_ID, USERNAME = user.USERNAME, CREATED_BY = user.CREATED_BY, CREATED_DATE = user.CREATED_DATE )@app.route('/users')def list_users(): users = User.query.all() return jsonify(list(map(user_to_dict, users)))@app.route('/users/')def find_user(userid): user = User.query.get(userid) return jsonify(user_to_dict(user))if __name__ == "__main__": app.run(debug=True)
在本例中,user_to_dict()
函数实现了将 user 对象转换为 dict,但这种写法是硬编码的,有多少个 Model 就要写多少个函数,所以,我们接下来考虑如何实现通用的代码。
对于 User 的实例,可以用 __dict__
特殊属性获取实例的字段,为了通用化,将代码放在一个基类中:
class EntityBase(object): def to_json(self): fields = self.__dict__ if "_sa_instance_state" in fields: del fields["_sa_instance_state"] return fields
然后在 Model 中通过多重继承,让 model 继承 EntitiBase
类,这样就不用改变每个 model 类的代码。为了方便叙述和学习,也给出第二种方法的完整代码:
from flask import Flask, jsonifyfrom flask_sqlalchemy import SQLAlchemyimport osfrom collections import OrderedDictapp = Flask(__name__)# application configurationsapp.config['SECURITY_KEY'] = 'you will never guess'app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DB_URI']app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Trueapp.config['JSON_SORT_KEYS'] = Falsedb = SQLAlchemy(app)class EntityBase(object): def to_json(self): fields = self.__dict__ if "_sa_instance_state" in fields: del fields["_sa_instance_state"] return fieldsclass User(db.Model, EntityBase): __tablename__ = 'user' USER_ID = db.Column(db.Integer, primary_key=True) USERNAME = db.Column(db.String(20)) CREATED_BY = db.Column(db.String(20)) CREATED_DATE = db.Column(db.Date)@app.route('/users')def list_users(): users = User.query.all() users_output = [] for user in users: users_output.append(user.to_json()) return jsonify(users_output)@app.route('/users/')def find_user(userid): user = User.query.get(userid) return jsonify(user.to_json())if __name__ == "__main__": app.run(debug=True)
如果有多个表,并且有关联,以上方法需要更多的手工代码。比较好的方法是使用第三方模块:Flask-Marshmallow,这个也是我想推荐的方法。通过 pip 安装 Flask-Marshmallow 模块后,我们需要定义一个 UserSchema 类,并且确定 UserSchema 对应到 User,如下面的代码:
from flask_marshmallow import Marshmallowma = Marshmallow(app)class UserSchema(ma.ModelSchema): class Meta: model = User
然后在路由中,可以方便的通过 dump()
方法转换为 dict。
@app.route('/users')def list_users(): users = User.query.all() user_schema = UserSchema(many=True) user_data = user_schema.dump(users) return jsonify(user_data)@app.route('/users/')def find_user(userid): user = User.query.get(userid) user_schema = UserSchema() user_data = user_schema.dump(user) return jsonify(user_data)
完整代码如下:
from flask import Flask, jsonifyfrom flask_marshmallow import Marshmallowfrom flask_sqlalchemy import SQLAlchemyimport osapp = Flask(__name__)# application configurationsapp.config['SECURITY_KEY'] = 'you will never guess'app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DB_URI']app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Trueapp.config['JSON_SORT_KEYS'] = Falsedb = SQLAlchemy(app)ma = Marshmallow(app)class User(db.Model): __tablename__ = 'user' USER_ID = db.Column(db.Integer, primary_key=True) USERNAME = db.Column(db.String(20), nullable=False) CREATED_BY = db.Column(db.String(20), nullable=False) CREATED_DATE = db.Column(db.Date, nullable=False)class UserSchema(ma.ModelSchema): class Meta: model = User@app.route('/users')def list_users(): users = User.query.all() user_schema = UserSchema(many=True) user_data = user_schema.dump(users).data return jsonify(user_data)@app.route('/users/')def find_user(userid): user = User.query.get(userid) user_schema = UserSchema() user_data = user_schema.dump(user).data return jsonify(user_data)if __name__ == "__main__": app.run(debug=True)
源码放在 上。
转载地址:http://sbthz.baihongyu.com/