2010-10-21 1 views
5

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

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) .Все() можно применять запросы к списку коллекций ... но как я могу сделать обратное? Я хотел бы получить первые 10 коллекций, которые делает учетная запись , а не.

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

ответ

5

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

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() 
... 
+0

Ха. Мне явно нужно много узнать о sqlalchemy. :) Спасибо! – Hoopes

Смежные вопросы