Um group.members
zu sortieren, müssen die Personen zum Sortieren vorhanden sein, während die GroupMembership-Assoziationsobjekte geladen werden. Dies kann mit einem Join erreicht werden.
In der aktuellen Konfiguration group.members
erste lädt die GroupMembership Objekte, Füllen group.group_memberships
Beziehung, und dann feuert ein SELECT für jede Person als der Verein Proxy greift die GroupMembership.person
Beziehung Attribute zugreifen.
Stattdessen wollen Sie sowohl die GroupMemberships und Personen in derselben Abfrage laden, sortiert nach 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
Sie müssen die order_by='Person.last_name'
auf die skalare Beziehung GroupMembership.person
Group.group_memberships
anstelle des backref Attribut definieren, die geeignet sind, scheint logisch zu sein. Auf der anderen Seite gibt order_by
"die Reihenfolge an, die beim Laden dieser Elemente angewendet werden sollte", so dass es sinnvoll ist, wenn Sie joined loading verwenden. Da Sie einer Viele-zu-Eins-Referenz beitreten und der Fremdschlüssel nicht nullbar ist, können Sie einen Inner-Join verwenden.
Mit der Definition in Ort:
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']
Ein Nachteil dieser Lösung ist, dass die person
Beziehung immer mit Spannung geladen wird, und die Reihenfolge angewandt, BY, wenn für GroupMemberships Abfrage:
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]:
...
Sie don die Argumente 'uselist = False' brauchen nicht für die Beziehungen, wie sie auf der referenzierenden Seite definiert sind, oder anders ausgedrückt, eine' GroupMembership'-Entität kann nur auf eine 'Person' und eine 'Gruppe' verweisen. Sie würden es in eins-zu-eins-Beziehungen verwenden. –
Nur um sicher zu sein, möchten Sie GroupMembership Objekte im Allgemeinen manuell behandeln? Mit anderen Worten, ist es üblich, dass Sie nur die GroupMemberships auswählen/abfragen? –