使用嵌套字段加载/反序列化对象

时间:2019-08-09 03:21:19

标签: python sqlalchemy marshmallow

我有两个pip install package_name 模型-sqlalchemyServiceRecord,它们之间的关系是Service,可以通过many-to-many表来解决。 我正在尝试从以下JSON反序列化service_record_services对象,并通过提供的ServiceRecord从数据库加载Service对象。相反,我最终创建了新的ids对象。

Service

型号:

# from POST
{'service_date': '08/21/2019 08:00 pm', 'site_id': 33, 'subcontractor_id': 37, 'services': [{'id':1},{'id': 2}]}

模式:

class Service(db.Model):
    __tablename__ = 'services'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False, unique=True)
    comments = db.Column(db.String(200), nullable=True, unique=False)

class ServiceRecord(db.Model):
    __tablename__ = 'service_records'
    id = db.Column(db.Integer, primary_key=True)
    created = db.Column(db.DateTime, server_default=db.func.now())
    datetime = db.Column(db.DateTime)
    subcontractor_id = db.Column(db.Integer, db.ForeignKey('subcontractors.id'))
    subcontractor = db.relationship( 'Subcontractor', back_populates='service_records')
    site_id = db.Column(db.Integer, db.ForeignKey('sites.id'))
    site = db.relationship('Site', back_populates='service_records')
    # all services for this record
    services = db.relationship('Service', secondary=lambda: service_record_services)
class ServiceSchema(ma.ModelSchema):
    class Meta:
        include_fk = True
        model = models.Service
        strict = False
        sqla_session = db.session
        transient = True

    name = fields.Str(dump_only=True)

class ServiceRecordSchema(ma.ModelSchema):
    class Meta:
        include_fk = True
        model = models.ServiceRecord
        sqla_session = db.session

    id = fields.Int(dump_only=True)
    subcontractor_name = fields.Function(lambda obj: obj.subcontractor.name, dump_only=True)
    site_name = fields.Function(lambda obj: obj.site.name, dump_only=True)
    services = fields.Nested(ServiceSchema, many=True)
    service_date = fields.DateTime(format='%m/%d/%Y %I:%M %p', attribute='datetime')

    @pre_load
    def process_services(self, data):
        current_app.logger.debug('[pre_load - 1] data: {}'.format(data))
        service_ids = map(lambda x: x.get('id'), data.get('services'))
        services = models.Service.query.filter(models.Service.id.in_(service_ids)).all()
        # i'd like to be able to use these Service objects in the loaded ServiceRecord
        data['_services'] = services
        return data

1 个答案:

答案 0 :(得分:0)

原来,我要做的就是将两个必填字段添加到我的ServiceSchema中,删除transient=True就是这样。这是工作代码:

class ServiceSchema(ma.ModelSchema):
    class Meta:
        include_fk = True
        model = models.Service
        strict = False
        sqla_session = db.session

    id = fields.Int()
    name = fields.Str()

class ServiceRecordSchema(ma.ModelSchema):
    class Meta:
        include_fk = True
        model = models.ServiceRecord
        sqla_session = db.session

    id = fields.Int(dump_only=True)
    subcontractor_name = fields.Function(lambda obj: obj.subcontractor.name, dump_only=True)
    site_name = fields.Function(lambda obj: obj.site.name, dump_only=True)
    service_date = fields.DateTime(format='%m/%d/%Y %I:%M %p', attribute='datetime')
    services = fields.Nested(ServiceSchema, many=True)