我有一个简单的数据结构,其中电影表具有国家/地区表的外键。
为了检索来自同一国家的所有电影,我将这个属性设为'same_country_films',这是一种自我指涉的关系。
它几乎完成了正确的工作,但是,它还包括列表中的电影本身。我怎样才能排除,只有其他电影?
非常感谢!
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import mapper, relationship
metadata = MetaData()
country_table = Table('country', metadata,
Column('id', String, primary_key=True),
Column('name', String),
)
film_table = Table('film', metadata,
Column('id', Integer, primary_key=True),
Column('title', String),
Column('year', Integer),
Column('country_id', Integer, ForeignKey('country.id'))
)
class Country(object):
pass
class Film(object):
pass
mapper(Country, country_table)
mapper(Film, film_table,
properties={
'country':relationship(
Country,
backref='films'),
'same_country_films':relationship(
Film,
primaryjoin=film_table.c.country_id==\
film_table.c.country_id,
foreign_keys=[
film_table.c.country_id,
]
)
}
)
答案 0 :(得分:3)
最简单的解决方案是自己编写此属性而不是关系:
class Film(object):
@property
def same_country_films(self):
return [f for f in self.country.films if f!=self]
在会话生命期间访问film.same_country_films
和country.films
时,此解决方案不会对此属性执行单独查询。该属性无法更新,因为您通常可以使用关系,但我怀疑它真的需要。
糟糕的是,它是针对每次访问进行评估的(而不是那么多工作)。您可以将property
装饰器更改为chaching one(如werkzeug中的cached_property
),但在首次访问该属性后,该属性不会反映country.films
中的更改。
答案 1 :(得分:0)
我认为应该这样做,(虽然我实际上没有测试过它):
primaryjoin=sqlalchemy.and_(
film_table.c.country_id==film_table.c.country_id,
film_table.c.id!=film_table.c.id)