【问题标题】:SQLAlchemy: Simple ordering across many-to-many relationship [duplicate]SQLAlchemy:跨多对多关系的简单排序[重复]
【发布时间】:2018-04-06 00:13:48
【问题描述】:

我对 SQLAlchemy 还很陌生,我正在尝试弄清楚如何在与关联对象的多对多关系中设置最简单的 order_by。我在这里看到了一些关于按计数排序的问题,但不是这个更基本的问题。

假设这些表(从实际的简化):

class Event(db.Model):
    __tablename__ = 'event'
    id = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String(255))
    date = db.Column(db.Date)

    guests = db.relationship('Guest_Event', back_populates='event')

class Guest(db.Model):
    __tablename__ = 'guest'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(256))

    events = db.relationship('Guest_Event', back_populates='guest')

class Guest_Event(db.Model):
    __tablename__ = 'guest_event'
    id = db.Column('id', db.Integer, primary_key=True)
    guest_id = db.Column('guest_id', db.Integer, db.ForeignKey('guest.id'))
    event_id = db.Column('event_id', db.Integer, db.ForeignKey('event.id'))
    guest = db.relationship('Guest', back_populates='events')
    event = db.relationship('Event', back_populates='guests')

我想做的就是拥有类似的东西:

event = Event.query.get(id)
# Then in a Jinja2 template:
<p>The following people were at this event:</p>
{% for guest_event in event.guests %}
  {{ guest_event.guest.name }} <br/>
{% endfor %}

此列表按 guest.name 或类似方式排序

guest = Guest.query.get(id)
# Jinja2:
<p>{{ guest.name }} was at these events:</p>
{% for guest_event in guest.events %}
    {{ guest_event.event.date }}: {{ guest_event.event.description }}<br/>
{% endfor %}

这是按 event.date 排序的,可能是降序的。

我尝试将order_by='Guest.name' 放在Guest_Event 类或Event 类中,两者都抛出SQL 错误“Unknown column guest.name in order 子句”,这并不奇怪,因为此查询仅在关联表上运行.但我不知道还能做什么。

最终我想做一个关联代理,因为我只想能够直接执行for guest in event.guests 然后guest.name,而不是打扰关联类。

另外:您将如何动态更改此查询?例如,如果我想按 event.date 在一种情况下升序、在另一种情况下降序或按我在此简化示例中未显示的其他事项对事件进行排序。

【问题讨论】:

  • 简而言之,在Guest_Event关联对象模型中使用guest = db.relationship('Guest', back_populates='events', lazy='joined', order_by='Guest.name')

标签: python sqlalchemy


【解决方案1】:

要么:

1) 构造一个新的查询

guests = Guest.query.\
    join(Guest_Event).\
    join(Event).\
    filter(Event.id == event.id).\
    order_by(asc(Guest.name))

并循环遍历这些结果,或者

2) 使用 Python 进行排序:

 for guest_event in sorted(event.guests, key=lambda x: x.name):

【讨论】:

  • 我要补充一点,如果您使用 Table 而不是 Model 作为关联对象,您应该可以通过 Guest_Event 摆脱联接。见docs.sqlalchemy.org/en/latest/orm/…
  • 谢谢。这确实有效,尽管我曾希望有一个不那么混乱的解决方案。我不能使用 Table 作为关联对象;这是一个简化的示例,在真实的 Guest_Event 表中,我还有在其他上下文中使用的其他列。
  • 是的,这是您为在关系表中包含非链接列并需要即时更改排序所付出的代价。如果您查看链接的重复问题,则有一个在关系中硬编码顺序的示例 - 但这可能仅适用于显式连接(文档含糊不清)。
猜你喜欢
  • 2011-08-23
  • 1970-01-01
  • 2015-10-21
  • 2014-08-25
  • 2018-02-24
  • 2018-05-03
  • 1970-01-01
  • 2014-05-17
  • 1970-01-01
相关资源
最近更新 更多