如何构造一个 API 端点,外键被它们的值替换?
How to construct an API endpoint with foreign keys replaced by their values?
我目前正在使用 Flask、SQLAlchemy 和 Marshmallow 构建 API。我有一个相当简单的数据库模型,如下所示:
class Transaction(db.Model):
#Transaction Model
__tablename__ = 'transactions'
id = db.Column(db.Integer, primary_key = True)
created_at = db.Column(db.DateTime, default=datetime.datetime.now)
date = db.Column(db.DateTime)
description = db.Column(db.Text)
amount = db.Column(db.Float)
category_id = db.Column(db.Integer, db.ForeignKey('categories.id'))
category = db.relationship('Category', uselist=False, lazy='select')
sub_category_id = db.Column(db.Integer, db.ForeignKey('sub_categories.id'))
sub_category = db.relationship('SubCategory', uselist=False, lazy='select')
account = db.Column(db.Integer, db.ForeignKey('accounts.id'))
inner_transfer = db.Column(db.Boolean)
class Category(db.Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key = True)
category = db.Column(db.String(64), unique = True)
transaction = db.relationship('Transaction')
我的棉花糖架构如下所示:
class CategorySchema(ma.ModelSchema):
class Meta:
model = Category
category_schema = CategorySchema()
categories_schema = CategorySchema(many=True)
class TransactionSchema(ma.ModelSchema):
class Meta:
model = Transaction
include_fk = True
还有一个非常简单的 API 端点:
@api.route('/transactions', methods=['GET'])
def transactions():
all_transactions = Transaction.query.all()
for transaction in all_transactions:
transaction.category = Category.query.filter_by(id=transaction.category_id).first()
print(transaction.category)
items, errors = transactions_schema.dump(all_transactions)
return jsonify(items)
我现在的问题:如何构建一个 JSON 响应,其中包含类别名称而不是其中的主键?我尝试了 "for transaction in all transactions" 位,在打印语句中我得到了类别名称,但它没有显示在我的 JSON 响应中...
我不太确定如何编写数据库模型。我特别坚持的是 db.relationship。在我的事务 class 中声明它似乎没有帮助,因为它也只显示类别 class 的主键。我上下阅读了 Flask-SQLAlchemy 文档,但我一无所知。
非常感谢任何帮助和指点!
谢谢!
我创建了您的模型的一个简单版本来实际展示这一点,并在数据库中植入了两个测试记录:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
ma = Marshmallow(app)
# DB Models
class Transaction(db.Model):
#Transaction Model
__tablename__ = 'transactions'
id = db.Column(db.Integer, primary_key = True)
category_id = db.Column(db.Integer, db.ForeignKey('categories.id'))
category = db.relationship('Category', uselist=False, lazy='select')
class Category(db.Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key = True)
category = db.Column(db.String(64), unique = True)
transaction = db.relationship('Transaction')
# Schema
class TransactionSchema(ma.ModelSchema):
class Meta:
model = Transaction
include_fk = True
# Here is the function, you do not not need to define all fields you want to dump
category_name = ma.Function(lambda obj: obj.category.category)
然后调用:
TransactionSchema(many=True).dump(Transaction.query.all()).data
产量:
[{u'category': 1, u'category_id': 1, u'category_name': u'Test1', u'id': 1},
{u'category': 2, u'category_id': 2, u'category_name': u'Test2', u'id': 2}]
也可以只用函数覆盖您的字段并使其仅转储:
class TransactionSchema(ma.ModelSchema):
class Meta:
model = Transaction
include_fk = True
category = ma.Function(lambda obj: obj.category.category, dump_only=True)
产量:
[{u'category': u'Test1', u'category_id': 1, u'id': 1},
{u'category': u'Test2', u'category_id': 2, u'id': 2}]
我目前正在使用 Flask、SQLAlchemy 和 Marshmallow 构建 API。我有一个相当简单的数据库模型,如下所示:
class Transaction(db.Model):
#Transaction Model
__tablename__ = 'transactions'
id = db.Column(db.Integer, primary_key = True)
created_at = db.Column(db.DateTime, default=datetime.datetime.now)
date = db.Column(db.DateTime)
description = db.Column(db.Text)
amount = db.Column(db.Float)
category_id = db.Column(db.Integer, db.ForeignKey('categories.id'))
category = db.relationship('Category', uselist=False, lazy='select')
sub_category_id = db.Column(db.Integer, db.ForeignKey('sub_categories.id'))
sub_category = db.relationship('SubCategory', uselist=False, lazy='select')
account = db.Column(db.Integer, db.ForeignKey('accounts.id'))
inner_transfer = db.Column(db.Boolean)
class Category(db.Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key = True)
category = db.Column(db.String(64), unique = True)
transaction = db.relationship('Transaction')
我的棉花糖架构如下所示:
class CategorySchema(ma.ModelSchema):
class Meta:
model = Category
category_schema = CategorySchema()
categories_schema = CategorySchema(many=True)
class TransactionSchema(ma.ModelSchema):
class Meta:
model = Transaction
include_fk = True
还有一个非常简单的 API 端点:
@api.route('/transactions', methods=['GET'])
def transactions():
all_transactions = Transaction.query.all()
for transaction in all_transactions:
transaction.category = Category.query.filter_by(id=transaction.category_id).first()
print(transaction.category)
items, errors = transactions_schema.dump(all_transactions)
return jsonify(items)
我现在的问题:如何构建一个 JSON 响应,其中包含类别名称而不是其中的主键?我尝试了 "for transaction in all transactions" 位,在打印语句中我得到了类别名称,但它没有显示在我的 JSON 响应中...
我不太确定如何编写数据库模型。我特别坚持的是 db.relationship。在我的事务 class 中声明它似乎没有帮助,因为它也只显示类别 class 的主键。我上下阅读了 Flask-SQLAlchemy 文档,但我一无所知。
非常感谢任何帮助和指点!
谢谢!
我创建了您的模型的一个简单版本来实际展示这一点,并在数据库中植入了两个测试记录:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
ma = Marshmallow(app)
# DB Models
class Transaction(db.Model):
#Transaction Model
__tablename__ = 'transactions'
id = db.Column(db.Integer, primary_key = True)
category_id = db.Column(db.Integer, db.ForeignKey('categories.id'))
category = db.relationship('Category', uselist=False, lazy='select')
class Category(db.Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key = True)
category = db.Column(db.String(64), unique = True)
transaction = db.relationship('Transaction')
# Schema
class TransactionSchema(ma.ModelSchema):
class Meta:
model = Transaction
include_fk = True
# Here is the function, you do not not need to define all fields you want to dump
category_name = ma.Function(lambda obj: obj.category.category)
然后调用:
TransactionSchema(many=True).dump(Transaction.query.all()).data
产量:
[{u'category': 1, u'category_id': 1, u'category_name': u'Test1', u'id': 1},
{u'category': 2, u'category_id': 2, u'category_name': u'Test2', u'id': 2}]
也可以只用函数覆盖您的字段并使其仅转储:
class TransactionSchema(ma.ModelSchema):
class Meta:
model = Transaction
include_fk = True
category = ma.Function(lambda obj: obj.category.category, dump_only=True)
产量:
[{u'category': u'Test1', u'category_id': 1, u'id': 1},
{u'category': u'Test2', u'category_id': 2, u'id': 2}]