2017-06-20 5 views
3

アソシエーションオブジェクトを使用してSQLAlchemyのFlaskアプリケーションに多対多リレーションシップを設定しました。次に、クラス間にアソシエーション・プロキシーを設定して、関連オブジェクトを経由するのではなく、より直接的なアクセスを行いました。ここでSQLAlchemy order_byアソシエーションプロキシ経由で多対多のリレーションシップ

は、セットアップの簡略例です。

class Person(Model): 
    __tablename__ = 'persons' 
    id = Column(Integer, primary_key=True) 
    last_name = Column(Text, nullable=False) 
    groups = association_proxy('group_memberships', 'group') 
    # Other stuff 

class Group(Model): 
    __tablename__ = 'groups' 
    id = Column(Integer, primary_key=True) 
    name = Column(Text, nullable=False) 
    members = association_proxy('group_memberships', 'person') 
    # Other stuff 

class GroupMembership(Model): 
    __tablename__ = 'group_memberships' 
    id = Column(Integer, primary_key=True) 
    person_id = Column(Integer, ForeignKey('persons.id'), nullable=False) 
    group_id = Column(Integer, ForeignKey('groups.id'), nullable=False) 
    person = relationship('Person', uselist=False, backref=backref('group_memberships', cascade='all, delete-orphan')) 
    group = relationship('Group', uselist=False, backref=backref('group_memberships', cascade='all, delete-orphan'))  
    # Other stuff 

私は私の人生を把握することはできませんのためにどのようなメンバーがlast_nameによってソートするgroup.membersによって返さを取得する方法ですか?

+0

あなたドンそれが参照側で定義されているように関係上の 'uselist = False'引数を必要としません。つまり、' GroupMembership'エンティティは 'Person'と' Group'を参照できます。あなたは1対1の関係でそれを使用します。 –

+0

GroupMembershipオブジェクトを一般的に手作業で扱いたいのですか?つまり、GroupMembershipsだけをSELECT /クエリするのは一般的ですか? –

答えて

5

group.membersをソートするには、GroupMembership関連オブジェクトを読み込み中にソートできる人を持っている必要があります。これは結合で実現できます。 group.membersが最初にロードGroupMembershipオブジェクトにアクセスし、あなたの現在の構成では

group.group_memberships関係を満たし、かつ関連プロキシはGroupMembership.person関係属性アクセスのように各人のためのSELECTが発生します。

代わりにあなたがPerson.last_nameによって並べ替え同じクエリにGroupMembershipsと人の両方をロードしたい:、あなたが代わりに後方参照Group.group_membershipsのスカラー関係属性GroupMembership.personorder_by='Person.last_name'を定義する必要が

class GroupMembership(Model): 
    __tablename__ = 'group_memberships' 
    id = Column(Integer, primary_key=True) 
    person_id = Column(Integer, ForeignKey('persons.id'), nullable=False) 
    group_id = Column(Integer, ForeignKey('groups.id'), nullable=False) 
    person = relationship('Person', 
          backref=backref('group_memberships', 
              cascade='all, delete-orphan'), 
          lazy='joined', innerjoin=True, 
          order_by='Person.last_name') 
    group = relationship('Group', backref=backref('group_memberships', 
                cascade='all, delete-orphan')) 
    # Other stuff 

ている可能性やるべき論理的なもののように思える。一方、order_byは「これらのアイテムをロードするときに適用する順序を示す」ので、joined loadingを使用すると意味があります。あなたは多対1の参照に参加しているので、外部キーはNULL可能ではないため、内部結合を使用できます。代わりに与えられた定義に

In [5]: g = Group(name='The Group') 

In [6]: session.add_all([GroupMembership(person=Person(last_name=str(i)), group=g) 
    ...:     for i in range(30, 20, -1)]) 

In [7]: session.commit() 

In [8]: g.members 
2017-06-29 09:17:37,652 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) 
2017-06-29 09:17:37,653 INFO sqlalchemy.engine.base.Engine SELECT groups.id AS groups_id, groups.name AS groups_name 
FROM groups 
WHERE groups.id = ? 
2017-06-29 09:17:37,653 INFO sqlalchemy.engine.base.Engine (1,) 
2017-06-29 09:17:37,655 INFO sqlalchemy.engine.base.Engine SELECT group_memberships.id AS group_memberships_id, group_memberships.person_id AS group_memberships_person_id, group_memberships.group_id AS group_memberships_group_id, persons_1.id AS persons_1_id, persons_1.last_name AS persons_1_last_name 
FROM group_memberships JOIN persons AS persons_1 ON persons_1.id = group_memberships.person_id 
WHERE ? = group_memberships.group_id ORDER BY persons_1.last_name 
2017-06-29 09:17:37,655 INFO sqlalchemy.engine.base.Engine (1,) 
Out[8]: [<__main__.Person object at 0x7f8f014bdac8>, <__main__.Person object at 0x7f8f014bdba8>, <__main__.Person object at 0x7f8f014bdc88>, <__main__.Person object at 0x7f8f01ddc390>, <__main__.Person object at 0x7f8f01ddc048>, <__main__.Person object at 0x7f8f014bdd30>, <__main__.Person object at 0x7f8f014bde10>, <__main__.Person object at 0x7f8f014bdef0>, <__main__.Person object at 0x7f8f014bdfd0>, <__main__.Person object at 0x7f8f0143b0f0>] 

In [9]: [p.last_name for p in _] 
Out[9]: ['21', '22', '23', '24', '25', '26', '27', '28', '29', '30'] 

この解決策の欠点はperson関係は常に熱心にロードされ、GroupMembershipsを照会するときに適用ORDER BYされていることである。

In [11]: session.query(GroupMembership).all() 
2017-06-29 12:33:28,578 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) 
2017-06-29 12:33:28,578 INFO sqlalchemy.engine.base.Engine SELECT group_memberships.id AS group_memberships_id, group_memberships.person_id AS group_memberships_person_id, group_memberships.group_id AS group_memberships_group_id, persons_1.id AS persons_1_id, persons_1.last_name AS persons_1_last_name 
FROM group_memberships JOIN persons AS persons_1 ON persons_1.id = group_memberships.person_id ORDER BY persons_1.last_name 
2017-06-29 12:33:28,578 INFO sqlalchemy.engine.base.Engine() 
Out[11]: 
    ... 
関連する問題