Сериализация sqlalchemy hybrid_property с использованием зефира

Я использую sqlalchemy и marshmallow в моем приложении RESTful flask для сериализации моих моделей. У меня есть hybrid_property, полученный в результате одного из моих взаимоотношений в этой модели. Теперь я хотел бы сериализовать это hybrid_property в моей схеме, используя схему из связанной модели.

Кто-нибудь делал это раньше? Вот мои соответствующие фрагменты кода. Когда я проверяю ответ, похоже, не включается last_assessment в сериализованную версию модели.

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

person James Russo    schedule 01.06.2018    source источник
comment
Просто из любопытства пробовали ли вы поставить декоратор @property поверх декоратора hybrid_property?   -  person Charles David    schedule 14.06.2018


Ответы (1)


Это немного хитро, но я считаю, что проблема в том, что строка if self.daily_rula_average_ranges.length > 0: вызывает ошибку AttributeError, потому что длина обычно не является атрибутом списков. Вы, наверное, имели в виду if len(self.daily_rula_average_ranges) > 0:.

Вот пример, не зависящий от ORM - сериализатор не возвращает поля, если возникает ошибка атрибута, но возвращает данные в порядке, если соответствующие данные возвращаются свойством:

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}}

Неудивительно, что зефир ведет себя таким образом, потому что атрибут, который вызывает AttributeError, будет выглядеть так, как будто этот атрибут не существует, например:

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

hasattr(Person(), 'last_assessment')
# Out: False
person Michael Nelson    schedule 15.06.2018
comment
Интересно, я постараюсь взглянуть на это исправление как можно скорее, чтобы наградить вас наградой, если это правильно. Придется подождать, пока я вернусь с работы, хотя, к сожалению - person James Russo; 15.06.2018
comment
Ага, похоже, это было исправление, большое вам спасибо. Я виню работу с рельсами - person James Russo; 16.06.2018