Ruby on Rails具有“多次通过”关联。例如,
store has_many :shelves
shelf has many :books
store has_many :books, through: :shelves
这将使我们能够致电store.books
并在商店中获得所有书籍。我想在Flask中复制此功能,但似乎找不到信息。
例如,这是用Python编写的一对多关系。店里有很多书架,书架上有很多书。
class Store(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
shelves = db.relationship('Shelf', backref='store')
class Shelf(db.Model):
id = db.Column(db.Integer, primary_key=True)
location = db.Column(db.String(120), nullable=False)
store_id = db.Column(db.Integer, db.ForeignKey('store.id'), nullable=False)
books = db.relationship('Book', backref='shelf')
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
shelf_id = db.Column(db.Integer, db.ForeignKey('shelf.id'), nullable=False)
使用当前编写的代码,我可以调用store.shelves
和shelf.books
。但是,要阅读书籍,我将不得不遍历书架并致电.books
。
是否可以在这里致电store.books
?
答案 0 :(得分:1)
在架子上循环会非常低效。将其留给数据库引擎。
您需要创建一个自定义查询来实现。如果要使用store.books
进行调用,可以在Store
类中创建属性:
class Store(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
shelves = db.relationship('Shelf', backref='store')
@property
def books(self):
query = Book.query.join(Shelf).join(Store).filter(Store.id == self.id)
return query.all()
答案 1 :(得分:1)
一个选择是将Shelf
用作“辅助”表并创建单边“多对多”关系,尽管实际上是一对表之间存在一对多关系:< / p>
class Store(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
shelves = db.relationship('Shelf', backref='store')
books = db.relationship('Book', secondary='shelf', viewonly=True)
最好将这种关系仅视为视图,因为如果将其附加到Store.books
列表中,则无法确定书籍应转到哪个书架。这与Rails定义关系的方式非常接近。