简体   繁体   中英

Serializing a sqlalchemy hybrid_property using marshmallow

I am using sqlalchemy and marshmallow in my RESTful flask application to serialize my models. I have a hybrid_property that comes from one of my relationships on that model. I would like to now serialize that hybrid_property in my schema using the schema from the related model.

Has anyone done this before? Here are my relevant pieces of code. It doesn't seem to be including the last_assessment in the serialized version of the model when I check the response

class Person(db.Model):
  daily_rula_average_ranges = db.relationship('DailyRulaAverageRange', order_by="DailyRulaAverageRange.date", back_populates='person')

  @hybrid_property
  def last_assessment(self):
    if self.daily_rula_average_ranges.length > 0:
      return self.daily_rula_average_ranges[-1]

class PersonSchema(ma.Schema):
  last_assessment = ma.Nested(DailyRulaAverageRangeSchema, only=['id', 'date', 'risk'])
  class Meta:
    fields = ('last_assessment')

It's a bit sneaky, but I believe the problem is that the line if self.daily_rula_average_ranges.length > 0: is causing an AttributeError to be raised, because length is not usually an attribute of lists. You probably meant if len(self.daily_rula_average_ranges) > 0: .

Here's an ORM-agnostic example - the serializer returns no field if an attribute error is raised, but returns data fine if appropriate data is returned by the property:

from marshmallow import fields, Schema
from marshmallow.fields import Nested

class DailyRulaAverageRangeSchema(Schema):
    id=fields.UUID()
    date=fields.Date()
    risk=fields.Integer()

class PersonSchema(Schema):
    last_assessment = Nested(DailyRulaAverageRangeSchema, only=['id', 'date', 'risk'])
    class Meta:
        fields = ('last_assessment',)

class Person(object):
    @property
    def last_assessment(self):
        raise AttributeError('oops')

PersonSchema().dump(Person())

# Out[73]: {}

class Person(object):
    @property
    def last_assessment(self):
        return {"id": None, "date":None, 'risk': 100}   

PersonSchema().dump(Person())
# Out[83]: {u'last_assessment': {u'date': None, u'id': None, u'risk': 100}}

It is not too surprising that marshmallow behaves this way because an attribute that raises an AttributeError will appear as though the attribute does not exist, eg:

class Person(object):
    @property
    def last_assessment(self):
        raise AttributeError('oops')

hasattr(Person(), 'last_assessment')
# Out: False

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM