如何正确使用 Marshmallow 在 Mysql 上插入新数据?
How to use Marshmallow properly to insert new data on Mysql?
我将描述一个小型数据库结构:
一场拍卖有N件,一件物品可以参加N件拍卖。所以我们有多对多的情况,寻找我的代码:
Auction.py
from . import db, Base
itens = db.Table('auction_itens',
db.Column('item_id', db.Integer, db.ForeignKey('item.id'), primary_key=True),
db.Column('auction_id', db.Integer, db.ForeignKey('auction.id'), primary_key=True)
)
class Auction(Base):
name = db.Column(db.String(255), nullable=False)
itens = db.relationship('Item', secondary=itens, lazy='subquery',
backref=db.backref('auctions', lazy=True))
Item.py
from . import db, Base
class Item(Base):
name = db.Column(db.String(255), nullable=False)
这将创建以下结构:
这是我所期望的,但我的问题是在 post 上插入新数据库。因此,让我们看看我的架构和我的 post 以插入数据。
auctions_serializer.py
from .. import ma
from ..auctions import Auction
from .itens_serializer import ItemSchema
from marshmallow import fields
class AuctionSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Auction
include_relationships = True
load_instance = True
include_fk = True
itens = fields.Nested(ItemSchema, many=True)
itens_serializer.py
from .. import ma
from ..itens import Item
class ItemSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Item
include_relationships = True
load_instance = True
我去 post 的路线:
@bp_auctions.route('/auctions', methods=['POST'])
def postAuctions():
auction_schema = AuctionSchema()
auction = auction_schema.load(request.json)
current_app.db.session.add(auction)
current_app.db.session.commit()
return_msg = auction_schema.jsonify(auction)
return return_msg, return_code
如果此代码收到带有以下 JSON 的 post,则效果很好:
{
"name": "test",
"itens": ["item_one", "item_two"]
}
在这种情况下,代码将创建一个拍卖行,两行在项目中,两行在 auction_item 中,这是完美的,但如果我再次发送 post,序列化程序将不会搜索项目 table 上是否已存在“item_one”和“item_two”,它将在项目 table 上创建另一行,因此在这种情况下我的项目 table 将有 4 行,但有 2 个重复项。我的疑问是:
如何在基于 json 创建新项目之前强制 marshmallow 在 DB 上进行搜索?有什么办法吗?
我已经设法解决了问题,但看起来不像 optimal/cleanest 解决方案:
@bp_auctions.route('/auctions', methods=['POST'])
def postAuctions():
auction_schema = AuctionSchema()
itens_request = request.json.pop("itens")
auction = auction_schema.load(request.json)
itens_schema = ItemSchema()
for item in itens_request:
result = Item.query.filter_by(name=item["name"]).first()
if result is not None:
auction.itens.append(result)
else:
item = itens_schema.load(item)
auction.itens.append(item)
current_app.db.session.add(auction)
current_app.db.session.commit()
return_msg = auction_schema.jsonify(auction)
return return_msg, return_code
这个解决方案的问题是:对于每个带有X项的请求,将在数据库上进行X次选择。
如果有更大的问题,请IDK。
我将描述一个小型数据库结构:
一场拍卖有N件,一件物品可以参加N件拍卖。所以我们有多对多的情况,寻找我的代码:
Auction.py
from . import db, Base
itens = db.Table('auction_itens',
db.Column('item_id', db.Integer, db.ForeignKey('item.id'), primary_key=True),
db.Column('auction_id', db.Integer, db.ForeignKey('auction.id'), primary_key=True)
)
class Auction(Base):
name = db.Column(db.String(255), nullable=False)
itens = db.relationship('Item', secondary=itens, lazy='subquery',
backref=db.backref('auctions', lazy=True))
Item.py
from . import db, Base
class Item(Base):
name = db.Column(db.String(255), nullable=False)
这将创建以下结构:
这是我所期望的,但我的问题是在 post 上插入新数据库。因此,让我们看看我的架构和我的 post 以插入数据。
auctions_serializer.py
from .. import ma
from ..auctions import Auction
from .itens_serializer import ItemSchema
from marshmallow import fields
class AuctionSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Auction
include_relationships = True
load_instance = True
include_fk = True
itens = fields.Nested(ItemSchema, many=True)
itens_serializer.py
from .. import ma
from ..itens import Item
class ItemSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Item
include_relationships = True
load_instance = True
我去 post 的路线:
@bp_auctions.route('/auctions', methods=['POST'])
def postAuctions():
auction_schema = AuctionSchema()
auction = auction_schema.load(request.json)
current_app.db.session.add(auction)
current_app.db.session.commit()
return_msg = auction_schema.jsonify(auction)
return return_msg, return_code
如果此代码收到带有以下 JSON 的 post,则效果很好:
{
"name": "test",
"itens": ["item_one", "item_two"]
}
在这种情况下,代码将创建一个拍卖行,两行在项目中,两行在 auction_item 中,这是完美的,但如果我再次发送 post,序列化程序将不会搜索项目 table 上是否已存在“item_one”和“item_two”,它将在项目 table 上创建另一行,因此在这种情况下我的项目 table 将有 4 行,但有 2 个重复项。我的疑问是:
如何在基于 json 创建新项目之前强制 marshmallow 在 DB 上进行搜索?有什么办法吗?
我已经设法解决了问题,但看起来不像 optimal/cleanest 解决方案:
@bp_auctions.route('/auctions', methods=['POST'])
def postAuctions():
auction_schema = AuctionSchema()
itens_request = request.json.pop("itens")
auction = auction_schema.load(request.json)
itens_schema = ItemSchema()
for item in itens_request:
result = Item.query.filter_by(name=item["name"]).first()
if result is not None:
auction.itens.append(result)
else:
item = itens_schema.load(item)
auction.itens.append(item)
current_app.db.session.add(auction)
current_app.db.session.commit()
return_msg = auction_schema.jsonify(auction)
return return_msg, return_code
这个解决方案的问题是:对于每个带有X项的请求,将在数据库上进行X次选择。
如果有更大的问题,请IDK。