2012-01-21 13 views
4

は、コードは次のようになります具体的なクライアント - スーパーバイザー関係へのスケジュールですが、私はそれを行う方法を見つけていません。 SQLAlchemyのドキュメントを読むと、いくつかのヒントが見つかり、Schedule-TableのForeignKeyConstraintという結果になりました。SQLAlchemyの関係

この関連付けを行うにはどのように関係を指定できますか?

+0

別のsupervision_association_tableを持つ目的と、それに1対1の関係を持つScheduleクラスを使用する目的は何ですか?なぜ1つのテーブルを使用しないで、関連オブジェクトパターンを使用するのですか? http://www.sqlalchemy.org/docs/orm/relationships.html#association- object。いずれにしても、ここにsupervision_associaiton_tableをマップする必要があります。これは、2つの別々の「スケジュール」テーブルと「監督」テーブルを保持していれば、関連する一連の関係を作成する必要があります。 – zzzeek

+1

クライアントは本当にスーパーバイザを2人以上持つことができますか?あなたのM-N表は*はい*を示唆していますが、交渉の名前(監督者)は* No *を意味します。 – van

+0

@zzzeekスケジュールクラスに監督との1対多の関係を持たせて、1組のクライアント/スーパーバイザが多くの異なるスケジュールを持つことができるようにします。 – dasmaze

答えて

7

supervision_association_tableをマッピングして、そこから関係を作成できるようにする必要があります。

私はここで何かを艶出ししているかもしれませんが、ここに多対多があるので、実際にはClient.schedulesを持つことはできません。Client.schedules.append(some_schedule) "監督"それを指している?したがって、以下の例では、各SupervisorAssociationのScheduleコレクションに参加するための読み取り専用の「ロールアップ」アクセサが提供されています。 association_proxy拡張子は、SupervisionAssociationオブジェクトの詳細を便利に隠すために使用されます。

from sqlalchemy import Column, Integer, ForeignKey, Table, ForeignKeyConstraint, create_engine 
from sqlalchemy.orm import relationship, backref, scoped_session, sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.ext.associationproxy import association_proxy 
from itertools import chain 

Base = declarative_base() 

class SupervisionAssociation(Base): 
    __tablename__ = 'supervision' 

    supervisor_id = Column(Integer, ForeignKey('supervisor.id'), primary_key=True) 
    client_id = Column(Integer, ForeignKey('client.id'), primary_key=True) 

    supervisor = relationship("Supervisor", backref="client_associations") 
    client = relationship("Client", backref="supervisor_associations") 
    schedules = relationship("Schedule") 

class User(Base): 
    __tablename__ = 'user' 

    id = Column(Integer, primary_key=True) 

class Supervisor(User): 
    __tablename__ = 'supervisor' 
    __mapper_args__ = {'polymorphic_identity': 'supervisor'} 

    id = Column(Integer, ForeignKey('user.id'), primary_key = True) 

    clients = association_proxy("client_associations", "client", 
         creator=lambda c: SupervisionAssociation(client=c)) 

    @property 
    def schedules(self): 
     return list(chain(*[c.schedules for c in self.client_associations])) 

class Client(User): 
    __tablename__ = 'client' 
    __mapper_args__ = {'polymorphic_identity': 'client'} 

    id = Column(Integer, ForeignKey('user.id'), primary_key = True) 

    supervisors = association_proxy("supervisor_associations", "supervisor", 
         creator=lambda s: SupervisionAssociation(supervisor=s)) 
    @property 
    def schedules(self): 
     return list(chain(*[s.schedules for s in self.supervisor_associations])) 

class Schedule(Base): 
    __tablename__ = 'schedule' 
    __table_args__ = (
     ForeignKeyConstraint(['client_id', 'supervisor_id'], 
     ['supervision.client_id', 'supervision.supervisor_id']), 
    ) 

    id = Column(Integer, primary_key=True) 
    client_id = Column(Integer, nullable=False) 
    supervisor_id = Column(Integer, nullable=False) 
    client = association_proxy("supervisor_association", "client") 

engine = create_engine('sqlite:///temp.db', echo=True) 
db_session = scoped_session(sessionmaker(bind=engine)) 
Base.metadata.create_all(bind=engine) 

c1, c2 = Client(), Client() 
sp1, sp2 = Supervisor(), Supervisor() 
sch1, sch2, sch3 = Schedule(), Schedule(), Schedule() 

sp1.clients = [c1] 
c2.supervisors = [sp2] 
c2.supervisor_associations[0].schedules = [sch1, sch2] 
c1.supervisor_associations[0].schedules = [sch3] 

db_session.add_all([c1, c2, sp1, sp2, ]) 
db_session.commit() 


print c1.schedules 
print sp2.schedules 
+0

これは基本的に私が来たことです。関連テーブルのスケジュールを持ってクラスにマッピングします。私はそれをするかもしれませんが、私は協会のプロキシを使用しませんでした。これありがとう。 – dasmaze

関連する問題