Serialize two nested schemas with marshmallows

I am new to python. I have two SQLAlchemy models as follows:

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() 

I have two classes of Marshmallow schemes for them:

 class ListingSchema(Schema): id = fields.Int() title = fields.Str() location_id = fields.Int() class LocationSchema(Schema): id = fields.Int() title = fields.Str() 

I created a nested schema class, for example:

 class NestedSchema(Schema): listing = fields.Nested(ListingSchema) location fields.Nested(LocationSchema) 

I am making a connection request, for example:

 listing,location = db.session.query(Listing,Location)\ .join(Location, and_(Listing.location_id == Location.id))\ .filter(Listing.id == listing_id).first() 

The data is loaded into the objects that I checked. How can I parse this circuit? I tried

 result,errors = nested_listing_Schema(listing,location) 

This gives an error: "The listing object is not iterative."

+5
source share
1 answer

The rule is to use the class you created NestedSchema and not nested_schema, do the following:

 result,errors = NestedSchema().dump({'listing':listing,'location':location}) 

And the result will be as follows:

 dict: { u'listing': {u'id': 8, u'title': u'foo'}, u'location': {u'id': 30, u'title': u'bar'} } 

But I don’t understand why you wanted to create "NestedSchema", I think you can do it differently.

First forget the "NestedSchema" class.

After that, change your "ListingSchema", for example:

 class ListingSchema(Schema): id = fields.Int() title = fields.Str() location_id = fields.Int() location = fields.Nested("LocationSchema") #The diff is here 

And now you can do:

 listing = db.session.query(Listing).get(listing_id) # Suppose listing_id = 8 result,errors = ListingSchema().dump(listing) print result 

The result will be:

 dict: { u'id': 8, u'title': u'foo', u'location_id': 30, u'location': {u'id': 30, u'title': u'bar'} } 

Note that now "location" is a "listing" property.

And you can still make a Bilateral attachment , just add backref to the Listing (model) and add ListingSchema as nested in LocationSchema

 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 is that we have a one-to-many relationship. exclude=("location") should avoid recursion exclusion.

Now we can search by 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'}, ... ] } 

You can see the docs about it here.

+5
source

All Articles