用棉花糖序列化两个嵌套模式
Serialize two nested schema with marshmallow
我是 python 的新手。我有两个 SQLAlchemy 模型如下:
class listing(db.Model):
id = db.Integer(primary_key=True)
title = db.String()
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', lazy='joined')
class location(db.Model):
id = db.Integer(primary_key=True)
title = db.String()
我有两个 Marshmallow 架构 classes:
class ListingSchema(Schema):
id = fields.Int()
title = fields.Str()
location_id = fields.Int()
class LocationSchema(Schema):
id = fields.Int()
title = fields.Str()
我创建了一个嵌套架构 class,例如:
class NestedSchema(Schema):
listing = fields.Nested(ListingSchema)
location fields.Nested(LocationSchema)
我正在执行这样的连接查询:
listing,location = db.session.query(Listing,Location)\
.join(Location, and_(Listing.location_id == Location.id))\
.filter(Listing.id == listing_id).first()
数据加载到我检查过的对象中。如何解析这个模式?
我试过了
result,errors = nested_listing_Schema(listing,location)
这给出了错误:"Listing object is not iteratable."
正确的是使用你创建的 NestedSchema class 而不是 nested_schema,这样做:
result,errors = NestedSchema().dump({'listing':listing,'location':location})
结果将是:
dict: {
u'listing': {u'id': 8, u'title': u'foo'},
u'location': {u'id': 30, u'title': u'bar'}
}
但我不明白你为什么要做一个"NestedSchema",我想你可以用另一种方式做。
首先,忘记 class "NestedSchema"。
之后,改变你的"ListingSchema",像这样:
class ListingSchema(Schema):
id = fields.Int()
title = fields.Str()
location_id = fields.Int()
location = fields.Nested("LocationSchema") #The diff is here
现在您可以:
listing = db.session.query(Listing).get(listing_id) # Suppose listing_id = 8
result,errors = ListingSchema().dump(listing)
print result
结果将是:
dict: {
u'id': 8, u'title': u'foo', u'location_id': 30, u'location': {u'id': 30, u'title': u'bar'}
}
请注意,现在 "location" 是 "listing" 的 属性。
而且您仍然可以制作 Two-Way Nesting,只需在 Listing(模型)中添加一个 backref 并添加嵌套在 LocationSchema 中的 ListingSchema
class Listing(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(45), nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', lazy='joined', backref="listings") #the diff is here
class LocationSchema(Schema):
id = fields.Int()
title = fields.Str()
listings = fields.Nested("ListingSchema", many=True, exclude=("location",)) #The property name is the same as in bakcref
many=True
是因为我们有一个一对多的关系。
exclude=("location")
是为了避免递归异常。
现在我们也可以按位置搜索了。
location = db.session.query(Location).get(location_id) # Suppose location_id = 30
result,errors = LocationSchema().dump(location)
print result
dict: {u'id': 30, u'title': u'bar',
u'listings': [
{u'location_id': 30, u'id': 8, u'title': u'foo'},
{u'location_id': 30, u'id': 9, u'title': u'foo bar baz'},
...
]
}
你可以查看相关文档here
我是 python 的新手。我有两个 SQLAlchemy 模型如下:
class listing(db.Model):
id = db.Integer(primary_key=True)
title = db.String()
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', lazy='joined')
class location(db.Model):
id = db.Integer(primary_key=True)
title = db.String()
我有两个 Marshmallow 架构 classes:
class ListingSchema(Schema):
id = fields.Int()
title = fields.Str()
location_id = fields.Int()
class LocationSchema(Schema):
id = fields.Int()
title = fields.Str()
我创建了一个嵌套架构 class,例如:
class NestedSchema(Schema):
listing = fields.Nested(ListingSchema)
location fields.Nested(LocationSchema)
我正在执行这样的连接查询:
listing,location = db.session.query(Listing,Location)\
.join(Location, and_(Listing.location_id == Location.id))\
.filter(Listing.id == listing_id).first()
数据加载到我检查过的对象中。如何解析这个模式? 我试过了
result,errors = nested_listing_Schema(listing,location)
这给出了错误:"Listing object is not iteratable."
正确的是使用你创建的 NestedSchema class 而不是 nested_schema,这样做:
result,errors = NestedSchema().dump({'listing':listing,'location':location})
结果将是:
dict: {
u'listing': {u'id': 8, u'title': u'foo'},
u'location': {u'id': 30, u'title': u'bar'}
}
但我不明白你为什么要做一个"NestedSchema",我想你可以用另一种方式做。
首先,忘记 class "NestedSchema"。
之后,改变你的"ListingSchema",像这样:
class ListingSchema(Schema):
id = fields.Int()
title = fields.Str()
location_id = fields.Int()
location = fields.Nested("LocationSchema") #The diff is here
现在您可以:
listing = db.session.query(Listing).get(listing_id) # Suppose listing_id = 8
result,errors = ListingSchema().dump(listing)
print result
结果将是:
dict: {
u'id': 8, u'title': u'foo', u'location_id': 30, u'location': {u'id': 30, u'title': u'bar'}
}
请注意,现在 "location" 是 "listing" 的 属性。
而且您仍然可以制作 Two-Way Nesting,只需在 Listing(模型)中添加一个 backref 并添加嵌套在 LocationSchema 中的 ListingSchema
class Listing(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(45), nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', lazy='joined', backref="listings") #the diff is here
class LocationSchema(Schema):
id = fields.Int()
title = fields.Str()
listings = fields.Nested("ListingSchema", many=True, exclude=("location",)) #The property name is the same as in bakcref
many=True
是因为我们有一个一对多的关系。
exclude=("location")
是为了避免递归异常。
现在我们也可以按位置搜索了。
location = db.session.query(Location).get(location_id) # Suppose location_id = 30
result,errors = LocationSchema().dump(location)
print result
dict: {u'id': 30, u'title': u'bar',
u'listings': [
{u'location_id': 30, u'id': 8, u'title': u'foo'},
{u'location_id': 30, u'id': 9, u'title': u'foo bar baz'},
...
]
}
你可以查看相关文档here