SQLAlchemy python order_by parent 的 parent 的属性
SQLAlchemy python order_by parent's parent's attribute
我在订购时遇到了困难。我有一个 3 深度关系如下:
fight 1->M participant 1->M action
我需要按战斗 ID 排序动作列表。我找不到办法做到这一点。
class fight(db.Model):
fight_id = db.Column(db.Integer, primary_key=True)
fight_name = db.Column('fight_name')
class participant(db.Model):
participant_id = db.Column(db.Integer, primary_key=True)
participant_name = db.Column('participant_name')
fight_id = db.Column(db.Integer, db.ForeignKey("fight.fight_id"))
fight = db.relationship('fight', innerjoin=True)
class action(db.Model):
action_id = db.Column(db.Integer, primary_key=True)
participant_party_1 = db.Column(db.Integer, db.ForeignKey("participant.participant_id"))
participant_1 = db.relationship('participant', foreign_keys=[participant_1])
participant_party_2 = db.Column(db.Integer, db.ForeignKey("participant.participant_id"))
participant_2 = db.relationship('participant', foreign_keys=[participant_2])
我正在尝试做这样的事情?
action.query.order_by(action.<participant>.<fight_id>).all()
我真的需要 participant_1 和 participant_2 也完成。
您需要加入 Participant
模型,然后才能在查询中使用它。我按 DESC
对战斗 ID 进行了排序,以确保它正常工作。
q = session.query(Action).join(Action.participant_1).order_by(Participant.fight_id.desc(), Action.participant_party_1, Action.participant_party_2)
这是一个更大的例子,我更改了一些模型,因为我在运行时遇到了问题:
from datetime import datetime, date
from sqlalchemy import (
create_engine,
Text,
Integer,
String,
ForeignKey,
UniqueConstraint,
update,
DateTime,
Date,
Boolean,
LargeBinary,
nullslast,
Index,
)
from sqlalchemy.schema import (
Table,
Column,
MetaData,
)
from sqlalchemy.sql import select, and_, or_, func
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
metadata = MetaData()
Base = declarative_base(metadata=metadata)
engine = create_engine('postgresql+psycopg2://username:password@/dbname', echo=False)
class Fight(Base):
__tablename__ = "fights"
id = Column(Integer, primary_key=True)
name = Column(String)
class Participant(Base):
__tablename__ = "participants"
id = Column(Integer, primary_key=True)
name = Column(String)
fight_id = Column(Integer, ForeignKey("fights.id"))
fight = relationship('Fight', innerjoin=True)
class Action(Base):
__tablename__ = "actions"
id = Column(Integer, primary_key=True)
participant_party_1 = Column(Integer, ForeignKey("participants.id"))
participant_1 = relationship('Participant', foreign_keys=[participant_party_1])
participant_party_2 = Column(Integer, ForeignKey("participants.id"))
participant_2 = relationship('Participant', foreign_keys=[participant_party_2])
Base.metadata.create_all(engine)
with Session(engine) as session:
f1 = Fight(name="Sunday")
session.add(f1)
f2 = Fight(name="Monday")
session.add(f2)
p1 = Participant(name="P1", fight=f1)
p2 = Participant(name="P2", fight=f1)
p3 = Participant(name="P3", fight=f2)
p4 = Participant(name="P4", fight=f2)
session.add_all([p1, p2, p3, p4])
for action in range(5):
session.add(Action(participant_1=p1, participant_2=p2))
for action in range(3):
session.add(Action(participant_1=p3, participant_2=p4))
q = session.query(Action).join(Action.participant_1).order_by(Participant.fight_id.desc(), Action.participant_party_1, Action.participant_party_2)
for action in q.all():
print (action.participant_1.fight_id, action.participant_party_1, action.participant_party_2, action.id)
更大示例的输出
2 3 4 6
2 3 4 7
2 3 4 8
1 1 2 4
1 1 2 1
1 1 2 5
1 1 2 2
1 1 2 3
这对我来说不是完整的答案,但它是正确的方法。
action.query.join(participant, action.participant_party_1 == participant.participant_id).join(fight, participant.fight_id == fight.fight_id).order_by(fight.fight_id).order_by(action.attack_order).all()
非常感谢@IanWilson,但我为我的情况找到了一个更简单的答案。你让我找对地方了。
我在订购时遇到了困难。我有一个 3 深度关系如下:
fight 1->M participant 1->M action
我需要按战斗 ID 排序动作列表。我找不到办法做到这一点。
class fight(db.Model):
fight_id = db.Column(db.Integer, primary_key=True)
fight_name = db.Column('fight_name')
class participant(db.Model):
participant_id = db.Column(db.Integer, primary_key=True)
participant_name = db.Column('participant_name')
fight_id = db.Column(db.Integer, db.ForeignKey("fight.fight_id"))
fight = db.relationship('fight', innerjoin=True)
class action(db.Model):
action_id = db.Column(db.Integer, primary_key=True)
participant_party_1 = db.Column(db.Integer, db.ForeignKey("participant.participant_id"))
participant_1 = db.relationship('participant', foreign_keys=[participant_1])
participant_party_2 = db.Column(db.Integer, db.ForeignKey("participant.participant_id"))
participant_2 = db.relationship('participant', foreign_keys=[participant_2])
我正在尝试做这样的事情?
action.query.order_by(action.<participant>.<fight_id>).all()
我真的需要 participant_1 和 participant_2 也完成。
您需要加入 Participant
模型,然后才能在查询中使用它。我按 DESC
对战斗 ID 进行了排序,以确保它正常工作。
q = session.query(Action).join(Action.participant_1).order_by(Participant.fight_id.desc(), Action.participant_party_1, Action.participant_party_2)
这是一个更大的例子,我更改了一些模型,因为我在运行时遇到了问题:
from datetime import datetime, date
from sqlalchemy import (
create_engine,
Text,
Integer,
String,
ForeignKey,
UniqueConstraint,
update,
DateTime,
Date,
Boolean,
LargeBinary,
nullslast,
Index,
)
from sqlalchemy.schema import (
Table,
Column,
MetaData,
)
from sqlalchemy.sql import select, and_, or_, func
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
metadata = MetaData()
Base = declarative_base(metadata=metadata)
engine = create_engine('postgresql+psycopg2://username:password@/dbname', echo=False)
class Fight(Base):
__tablename__ = "fights"
id = Column(Integer, primary_key=True)
name = Column(String)
class Participant(Base):
__tablename__ = "participants"
id = Column(Integer, primary_key=True)
name = Column(String)
fight_id = Column(Integer, ForeignKey("fights.id"))
fight = relationship('Fight', innerjoin=True)
class Action(Base):
__tablename__ = "actions"
id = Column(Integer, primary_key=True)
participant_party_1 = Column(Integer, ForeignKey("participants.id"))
participant_1 = relationship('Participant', foreign_keys=[participant_party_1])
participant_party_2 = Column(Integer, ForeignKey("participants.id"))
participant_2 = relationship('Participant', foreign_keys=[participant_party_2])
Base.metadata.create_all(engine)
with Session(engine) as session:
f1 = Fight(name="Sunday")
session.add(f1)
f2 = Fight(name="Monday")
session.add(f2)
p1 = Participant(name="P1", fight=f1)
p2 = Participant(name="P2", fight=f1)
p3 = Participant(name="P3", fight=f2)
p4 = Participant(name="P4", fight=f2)
session.add_all([p1, p2, p3, p4])
for action in range(5):
session.add(Action(participant_1=p1, participant_2=p2))
for action in range(3):
session.add(Action(participant_1=p3, participant_2=p4))
q = session.query(Action).join(Action.participant_1).order_by(Participant.fight_id.desc(), Action.participant_party_1, Action.participant_party_2)
for action in q.all():
print (action.participant_1.fight_id, action.participant_party_1, action.participant_party_2, action.id)
更大示例的输出
2 3 4 6
2 3 4 7
2 3 4 8
1 1 2 4
1 1 2 1
1 1 2 5
1 1 2 2
1 1 2 3
这对我来说不是完整的答案,但它是正确的方法。
action.query.join(participant, action.participant_party_1 == participant.participant_id).join(fight, participant.fight_id == fight.fight_id).order_by(fight.fight_id).order_by(action.attack_order).all()
非常感谢@IanWilson,但我为我的情况找到了一个更简单的答案。你让我找对地方了。