sqlalchemy самореферентные отношения, не включая «я» - PullRequest
3 голосов
/ 14 апреля 2011

У меня есть простая структура данных, в которой таблица фильмов имеет внешний ключ к таблице стран.

Чтобы получить все фильмы из одной и той же страны, у меня есть свойство 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 ]

3 голосов
/ 21 апреля 2011

Самое простое решение состоит в том, чтобы кодировать это свойство самостоятельно вместо отношения:

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 на цепочку (например, cached_property в werkzeug), но тогда свойство не будет отражать изменения в country.films после первого доступа к нему.

0 голосов
/ 15 апреля 2011

Это должно сделать это, я думаю, (хотя я фактически не проверял это):

primaryjoin=sqlalchemy.and_(
    film_table.c.country_id==film_table.c.country_id,
    film_table.c.id!=film_table.c.id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...