python - 如何使用 Flask Marshmallow 将嵌套模式加入一个 JSON 对象
问题描述
我在将两个模式连接到一个嵌套 JSON 对象时遇到问题。此 API 作为 3 个相关表连接查询的结果返回 JSON。在我进行查询之后,我使用了从这里引用的两个 Marshmellow 模式。但是响应并不像预期的那样,这是响应:
{
"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(两个棉花糖模式)
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())
解决方案
您应该将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
。
推荐阅读
- linux - 我在使用 docker compose 安装多个应用程序时遇到问题
- javascript - 每次另一个函数的输出发生变化时如何运行一个函数?
- macos - 在 MAC 上运行 Powershell PS1(WMI?DB?)
- swift - Swift:测试使用委托调用的 URLSession
- json - 递归结构的 Json 模式不起作用
- python - 使用 flow_from_directory 时出现荒谬的损失和度量值
- javascript - 如何在 Vue.js 中 v-for 循环嵌套导航?
- c# - MD5 中的数据类型转换,无论是 SSIS 还是 C#
- selenium - 在使用 selenium(geckodriver)打开的浏览器上运行美丽的汤
- python-3.x - 如何在 python 中合并多个 xls 工作表?