2010-10-21 1 views
5

Es tut mir leid, wenn inverse nicht die bevorzugte Nomenklatur ist, die meine Suche behindert haben könnte. In jedem Fall habe ich es mit zwei deklarativen sqlalchemy-Klassen zu tun, was eine Viele-zu-Viele-Beziehung ist. Der erste ist Konto und der zweite ist Sammlung. Benutzer "kaufen" Sammlungen, aber ich möchte die ersten 10 Sammlungen zeigen, die der Benutzer noch nicht gekauft hat.sqlalchemy viele-zu-viele, aber umgekehrt?

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) 

Also, mit account.collections, kann ich alle Sammlungen erhalten, und mit dyn_coll.limit (1) .Alle() Ich kann Anfragen an die Liste von Sammlungen anwenden ... aber wie mache ich das umgekehrt? Ich möchte die ersten 10 Sammlungen erhalten, die das Konto nicht zugeordnet hat.

Jede Hilfe wird unglaublich geschätzt. Vielen Dank!

Antwort

5

Ich würde die Beziehung nicht für den Zweck verwenden, wie es technisch es nicht eine Beziehung ist, die Sie bauen (so würden alle Tricks, es auf beiden Seiten synchronisiert usw. nicht funktionieren).
IMO wäre die sauberste Weg, eine einfache Abfrage zu definieren, die Sie die Objekte zurück Haben Sie Ihre Suche:

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

Huh. Ich habe offensichtlich viel über sqlalchemy zu lernen. :) Danke! – Hoopes