SQLAlchemy:如何对关系字段的查询结果(order_by)进行排序?

Posted

技术标签:

【中文标题】SQLAlchemy:如何对关系字段的查询结果(order_by)进行排序?【英文标题】:SQLAlchemy: How to order query results (order_by) on a relationship's field? 【发布时间】:2012-04-09 08:35:57 【问题描述】:

型号

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Unicode
from sqlalchemy import TIMESTAMP
from sqlalchemy.orm import relationship

BaseModel = declarative_base()

class Base(BaseModel):
   __tablename__ = 'base'
   id = Column(Integer, primary_key=True)
   location = Column(Unicode(12), ForeignKey("locationterrain.location"), unique=True,)
   name = Column(Unicode(45))
   ownerid =  Column(Integer,ForeignKey("player.id"))
   occupierid =  Column(Integer, ForeignKey("player.id"))
   submitid =  Column(Integer,ForeignKey("player.id"))
   updateid =  Column(Integer,ForeignKey("player.id"))
   owner = relationship("Player",
         primaryjoin='Base.ownerid==Player.id',
         join_depth=3,
         lazy='joined')
   occupier= relationship("Player",
         primaryjoin='Base.occupierid==Player.id',
         join_depth=3,
         lazy='joined')
   submitter = relationship("Player",
         primaryjoin='Base.submitid== Player.id',
         join_depth=3,
         lazy='joined')
   updater= relationship("Player",
         primaryjoin='Base.updateid== Player.id',
         join_depth=3,
         lazy='joined')


class Player(BaseModel):
   __tablename__ = 'player'
   id = Column(Integer, ForeignKey("guildmember.playerid"), primary_key=True)
   name =  Column(Unicode(45))

搜索

bases = dbsession.query(Base)
bases = bases.order_by(Base.owner.name)

这不起作用....我到处搜索并阅读了文档。 但我只是不知道如何根据他们的“所有者”关系的名称对我的(基本)查询进行排序。

它总是会导致:

 AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'name'

这一定很容易……但我看不出来。还研究了比较器,这似乎是合乎逻辑的,但我看不到 ORDER BY 的查询部分是在哪里生成的,或者我应该返回什么,因为一切都是动态生成的。并且为我的每个“玩家”关系做一个比较器来做一件简单的事情似乎过于复杂。

【问题讨论】:

【参考方案1】:

SQLAlchemy 希望您从 SQL 的角度进行思考。如果你查询“Base”,那就是:

SELECT * FROM base

简单。那么,在 SQL 中,您将如何从“base”中选择行并在完全不同的表(即“player”)中按“name”列排序?您使用联接:

SELECT base.* FROM base JOIN player ON base.ownerid=player.id ORDER BY player.name

SQLAlchemy 有没有你使用相同的思维过程——你 join():

session.query(Base).join(Base.owner).order_by(Player.name)

【讨论】:

这是有道理的。但这确实意味着我一次只能加入一个玩家关系对吧?加入更多(无论出于何种原因......)意味着打破东西。因此,如果我想通过更新程序订购,我必须这样做: session.query(Base).join(Base.updater).order_by(Player.name) 或 'occupier': session.query (Base).join(Base.occupier).order_by(Player.name) 您可以使用该表的别名多次加入该表。这又是一个 SQL 概念,所以知道如何在 SQL 中解决问题意味着您将知道如何在 SQLAlchemy 中解决它。别名首先在docs.sqlalchemy.org/en/latest/orm/tutorial.html#using-aliases 引入。 这个答案将过滤掉任何base 对象,其中base.ownerid 为空。您知道如何修改按关系值排序的方法,但不排除关系中没有值的对象吗? (也许最后或第一个排序没有关系的) 如果有人好奇,我通过强制左连接来包含空关系。在使用 outerjoin 而不是 join 完成的 sqlalchemy 中。

以上是关于SQLAlchemy:如何对关系字段的查询结果(order_by)进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

了解 SQLAlchemy ForeignKey 关系查询结果

如何将 Sqlalchemy ORM 查询结果转换为包含关系的单个联接表?

sqlalchemy使用及序列化

按 sqlalchemy 中的连接别名排序

如何在flask-sqlalchemy查询最后一条记录

SQLAlchemy 获取类对象而不是实际结果