【问题标题】:How to join nested schema into one JSON object with Flask Marshmallow如何使用 Flask Marshmallow 将嵌套模式加入一个 JSON 对象
【发布时间】:2020-05-21 01:16:19
【问题描述】:

我在将两个模式连接到一个嵌套 JSON 对象时遇到问题。此 API 作为 3 个相关表连接查询的结果返回 JSON。在我进行查询后,我使用了两个 Marshmellow 架构,引用自 here。但是响应并不像预期的那样,下面是响应:

{
  "message": "success",
  "device": [
    {
      "device_name": "Kamar Tidur Utama"
    }
  ],
  "sensor": [
    {
      "value": 23.3683,
      "sensor_name": "Temperature"
    },
    {
      "value": 0.0,
      "sensor_name": "Motion"
    },
    {
      "value": 90.12,
      "sensor_name": "Humidity"
    },
    {
      "value": 15.8667,
      "sensor_name": "Current 1"
    },
    {
      "value": 15.0333,
      "sensor_name": "Current 2"
    }
  ]
}

我想要的是把“传感器”对象放在“设备”里面。很多设备都有很多这样的传感器:

{
  "message": "success",
  "device": [
    {
        "device_name": "Kamar Tidur Utama"
        "sensor": [
            {
            "value": 23.3683,
            "sensor_name": "Temperature"
            },
            {
            "value": 0.0,
            "sensor_name": "Motion"
            },
            {
            "value": 90.12,
            "sensor_name": "Humidity"
            },
            {
            "value": 15.8667,
            "sensor_name": "Current 1"
            },
            {
            "value": 15.0333,
            "sensor_name": "Current 2"
            }
        ]
    }
  ]
}

这是我的三个相关模型:

Device.py(一种查询 API 的方法)

 @classmethod
    def get_device_sensor(cls):
        device_sensor_schema = DeviceSensorSchema(many=True)
        sensor_value_schema = SensorValueSchema(many=True)

        device = Device.query.join(SensorData, Device.id == SensorData.device_id)\
            .add_columns(Device.name.label('device_name'))
        print(device)
        sensor = Sensor.query.join(SensorData, Sensor.id == SensorData.sensor_id)\
            .add_columns(Sensor.name.label('sensor_name'), SensorData.value.label('value'))

        res_device = device_sensor_schema.dump(device, many=True)
        res_sensor = sensor_value_schema.dump(sensor, many=True)
        if device:
            return jsonify({'message': 'success', 'device': res_device, 'sensor': res_sensor})
        else:
            return {'message': 'Table device is empty'}, 404

Device.py(两个 marshmellow 架构)

class SensorValueSchema(ma.Schema):
    sensor_name = fields.String()
    value = fields.Float()
    ordered=True

class DeviceSensorSchema(Schema):
    device_name = fields.String()
    sensors = fields.List(fields.Nested(SensorValueSchema))

Device.py(模型类)

class Device(db.Model):
    __tablename__ = "devices"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    name = db.Column(db.String(255))
    serial_number = db.Column(db.String(255), unique=True)
    used_relay = db.Column(db.Integer, default=0)
    created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
    updated_at = db.Column(db.DateTime(timezone=True), onupdate=db.func.now())
    switches = db.relationship('Switch', backref='device', lazy='dynamic')
    power_usages = db.relationship('PowerUsage', backref='device', lazy='dynamic')
    power_expenses = db.relationship('PowerExpense', backref='device', lazy='dynamic')
    behaviors_dataset = db.relationship('BehaviorDataset', backref='device', lazy='dynamic')
    usage_histories = db.relationship('UsageHistory', backref='device', lazy='dynamic')
    sensors_data = db.relationship('SensorData', backref='device', lazy='dynamic')
    notifications = db.relationship('Notification', backref='device', lazy='dynamic')
    device_serial_number = db.relationship('DeviceSerialNumber', backref='device', lazy='dynamic')

Sensor.py(模型类)

class Sensor(db.Model):
    __tablename__ = "sensors"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120))
    created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
    updated_at = db.Column(db.DateTime(timezone=True), onupdate=db.func.now())
    sensors_data = db.relationship('SensorData', backref='sensor', lazy='dynamic')

SensorData.py(模型类)

class SensorData(db.Model):
    __tablename__ = "sensors_data"
    id = db.Column(db.Integer, primary_key=True)
    device_id = db.Column(db.Integer, db.ForeignKey('devices.id'))
    sensor_id = db.Column(db.Integer, db.ForeignKey('sensors.id'))
    value = db.Column(db.Float)
    created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
    updated_at = db.Column(db.DateTime(timezone=True), onupdate=db.func.now())

【问题讨论】:

  • return jsonify({'message': 'success', 'device': res_device, 'sensor': res_sensor}) -> return jsonify({'message': 'success', 'device': res_device})device.sensors = sensorres_device = device_sensor_schema.dump(device, many=True)
  • @needtobe 您能否提供该方法的完整代码?当我尝试将该方法更改为 pastebin.com/S7ha3CAk 时,它对我不起作用

标签: python json flask flask-sqlalchemy marshmallow


【解决方案1】:

您应该将sensor 对象分配给device 列表中的每个条目。我实现理想结果的愚蠢方式:

 @classmethod
    def get_device_sensor(cls):
        device_sensor_schema = DeviceSensorSchema(many=True)
        sensor_value_schema = SensorValueSchema(many=True)

        device = Device.query.join(SensorData, Device.id == SensorData.device_id)\
            .add_columns(Device.name.label('device_name'))
        print(device)
        sensor = Sensor.query.join(SensorData, Sensor.id == SensorData.sensor_id)\
            .add_columns(Sensor.name.label('sensor_name'), SensorData.value.label('value'))

        res_device[0].sensors = sensor
        res_device = device_sensor_schema.dump(device, many=True)

        if device:
            return jsonify({'message': 'success', 'device': res_device})
        else:
            return {'message': 'Table device is empty'}, 404

为了解决这个问题,您可以使用映射的 SQLAlchemy 对象。在这种情况下Device.sensors_data

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-20
    • 2020-06-17
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    相关资源
    最近更新 更多