Python 如何通过多个级别的SQLAlchemy关系检索一组对象?
在以下设置中,如何从所有汽车轮胎中检索一组传感器数据 一辆汽车有很多轮胎,而一个轮胎只有一个传感器数据,所以在SQL中我会这样做 选择sd。* 从车上取c c.id=t.car\U id上的内侧连接轮胎 内部连接传感器数据为t.id上的sd=sd.tire\U id 氨基甲酸乙酯类: 通过 类别TireBase: 车=关系车,后参考=轮胎 类传感器数据库: 轮胎=关系轮胎,反向参考=反向参考传感器\数据,使用列表=错误 我猜有一种比下面更优雅的方式来获取所有传感器数据,但我找不到它 轮胎=Car.query.get1.tires 传感器数据=[轮胎传感器数据。轮胎传感器数据] 有人能提出更好的方法吗?我在想象我应该能做一些像 传感器数据=Car.query.get1.sensor\u数据 或 传感器数据=Car.query.get1.tires.sensor\u数据Python 如何通过多个级别的SQLAlchemy关系检索一组对象?,python,sqlalchemy,Python,Sqlalchemy,在以下设置中,如何从所有汽车轮胎中检索一组传感器数据 一辆汽车有很多轮胎,而一个轮胎只有一个传感器数据,所以在SQL中我会这样做 选择sd。* 从车上取c c.id=t.car\U id上的内侧连接轮胎 内部连接传感器数据为t.id上的sd=sd.tire\U id 氨基甲酸乙酯类: 通过 类别TireBase: 车=关系车,后参考=轮胎 类传感器数据库: 轮胎=关系轮胎,反向参考=反向参考传感器\数据,使用列表=错误 我猜有一种比下面更优雅的方式来获取所有传感器数据,但我找不到它 轮胎=Car
这些解决方案将在汽车上返回只读传感器数据属性,有关更多信息,请参阅注释:
class Car(Base):
id = Column(Integer, primary_key=True)
# results in a collection of sensor_data objects. This method is the
# cleanest reading by far, but behaves a little differently from the
# other two in terms of how the collection is constructed. Accessing
# the association proxy causes sqlalchemy to query the tire table for
# for the `Car`'s `Tire`s and then iterates over each one, accessing
# its `sensor_data` attribute to construct the collection on `Car`.
# With the lazy loading defaults, this resulted in 5 queries to
# construct the relationship, so depending on how you need to use it
# you might consider some sort of eager loading.
sensor_datas_aprox = association_proxy('tires', 'sensor_data')
# Joins Tire and SensorData. TBH the docs only mention
# using secondary in context of m:n relationship, but
# this seems to work OK.
sensor_datas_rel = relationship(
'SensorData',
secondary='join(Tire, SensorData)',
viewonly=True
)
# a query enabled property, queries for the data on
# access, pretty self explanatory.
@property
def sensor_datas_prop(self):
return object_session(self).query(SensorData).\
join(Tire).filter(
Tire.car_id == self.id,
SensorData.tire_id == Tire.id
).all()
class Tire(Base):
id = Column(Integer, primary_key=True)
car_id = Column(Integer, ForeignKey('car.id'))
car = relationship("Car", backref="tires")
class SensorData(Base):
tire_id = Column(Integer, ForeignKey('tire.id'), primary_key=True)
tire = relationship("Tire", backref=backref("sensor_data", uselist=False))
if __name__ == '__main__':
s = Session()
for _ in range(2):
car = Car()
car.tires = [Tire(sensor_data=SensorData()) for _ in range(4)]
s.add(car)
s.commit()
for car in s.query(Car):
print('*' * 100)
print(car.sensor_datas_rel)
print(car.sensor_datas_prop)
print(car.sensor_datas_aprox)
输出:
****************************************************************************************************
[SensorData(tire_id=1), SensorData(tire_id=2), SensorData(tire_id=3), SensorData(tire_id=4)]
[SensorData(tire_id=1), SensorData(tire_id=2), SensorData(tire_id=3), SensorData(tire_id=4)]
[SensorData(tire_id=1), SensorData(tire_id=2), SensorData(tire_id=3), SensorData(tire_id=4)]
****************************************************************************************************
[SensorData(tire_id=5), SensorData(tire_id=6), SensorData(tire_id=7), SensorData(tire_id=8)]
[SensorData(tire_id=5), SensorData(tire_id=6), SensorData(tire_id=7), SensorData(tire_id=8)]
[SensorData(tire_id=5), SensorData(tire_id=6), SensorData(tire_id=7), SensorData(tire_id=8)]
谢谢我一直在想我是否可以使用多对多列表中列出的辅助/关联功能。看到如何投射SensorData,我知道该怎么做,但不明白为什么必须指定过滤器。为什么不能利用现有的关系,避免重复?换句话说,如果我已经指定了外键/关系,为什么必须重新指定它们?不。这就是为什么我必须在传感器数据属性的筛选器中指定外键和表联接?或者为什么我必须在关系上指定primaryjoin,然后在传感器数据属性的筛选器调用中重复相同的信息?我还没有尝试过,但association_proxy可能是另一种选择,我自己也考虑过association proxy选项,但打了折扣,因为我认为它无法将轮胎和传感器数据之间的1:1关系转换为车上的一个集合,但在尝试之后,似乎确实如此。我已经更新了答案以包含它。