sqlalchemy многие ко многим, но обратные? - PullRequest
5 голосов
/ 21 октября 2010

Извините, если обратная номенклатура не является предпочтительной, что может помешать моему поиску. В любом случае я имею дело с двумя декларативными классами sqlalchemy, которые являются отношением многие ко многим. Первый - это аккаунт, а второй - коллекция. Пользователи «покупают» коллекции, но я хочу показать первые 10 коллекций, которые пользователь еще не купил .

from sqlalchemy import *
from sqlalchemy.orm import scoped_session, sessionmaker, relation
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)

account_to_collection_map = Table('account_to_collection_map', Base.metadata,
                                Column('account_id', Integer, ForeignKey('account.id')),
                                Column('collection_id', Integer, ForeignKey('collection.id')))

class Account(Base):
    __tablename__ = 'account'

    id = Column(Integer, primary_key=True)
    email = Column(String)

    collections = relation("Collection", secondary=account_to_collection_map)

    # use only for querying?
    dyn_coll = relation("Collection", secondary=account_to_collection_map, lazy='dynamic')

    def __init__(self, email):
        self.email = email

    def __repr__(self):
        return "<Acc(id=%s email=%s)>" % (self.id, self.email)

class Collection(Base):
    __tablename__ = 'collection'

    id = Column(Integer, primary_key=True)
    slug = Column(String)

    def __init__(self, slug):
        self.slug = slug

    def __repr__(self):
        return "<Coll(id=%s slug=%s)>" % (self.id, self.slug)

Итак, с помощью account.collections я могу получить все коллекции, а с помощью dyn_coll.limit (1) .all () я могу применить запросы к списку коллекций ... но как мне сделать обратное? Я хотел бы получить первые 10 коллекций, которые учетная запись не сопоставила.

Любая помощь невероятно ценится. Спасибо!

1 Ответ

5 голосов
/ 21 октября 2010

Я бы не использовал эти отношения для этой цели, поскольку технически это не отношения, которые вы строите (поэтому все приемы его синхронизации с обеих сторон и т. Д. Не будут работать). ИМО, самый простой способ - определить простой запрос, который вернет вам искомые объекты:

class Account(Base):
    ...
    # please note added *backref*, which is needed to build the 
    #query in Account.get_other_collections(...)
    collections = relation("Collection", secondary=account_to_collection_map, backref="accounts")

    def get_other_collections(self, maxrows=None):
        """ Returns the collections this Account does not have yet.  """
        q = Session.object_session(self).query(Collection)
        q = q.filter(~Collection.accounts.any(id=self.id))
        # note: you might also want to order the results
        return q[:maxrows] if maxrows else q.all()
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...