Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Самореферентные отношения sqlalchemy, не включая "я"

Автор вопроса: XuanОтветов: 2

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

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

pythonsqlalchemy

Ответы

Ответ 1 · рейтинг 3 · Denis Otkidach

Самое простое решение - закодировать это свойство самостоятельно вместо отношения:

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

Ответ 2 · Singletoned

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

primaryjoin=sqlalchemy.and_(
    film_table.c.country_id==film_table.c.country_id,
    film_table.c.id!=film_table.c.id)

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы