sqlalchemy自我参照关系不包括'自我'

时间:2011-04-14 16:54:11

标签: python sqlalchemy

我有一个简单的数据结构,其中电影表具有国家/地区表的外键。

为了检索来自同一国家的所有电影,我将这个属性设为'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,
                        ]
                    )
             }
    )

2 个答案:

答案 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_filmscountry.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)