【问题标题】:SQLAlchemy db.session.query() vs model.querySQLAlchemy db.session.query() 与 model.query
【发布时间】:2017-07-19 18:57:39
【问题描述】:

对于简单的返回所有结果查询,是否应该首选一种方法而不是另一种?我可以在网上找到两者的用途,但找不到任何描述差异的东西。

db.session.query([my model name]).all()

[my model name].query.all()

我觉得[我的模型名称].query.all() 更具描述性。

【问题讨论】:

标签: sqlalchemy


【解决方案1】:

很难给出明确的答案,因为回答这个问题存在高度的偏好主观性。

从一个角度来看,需要 db.session,因为第二种方法需要将其作为附加步骤合并到您的模型中 - 默认情况下,它作为 Base 类的一部分不存在。例如:

Base = declarative_base()
DBSession = scoped_session(sessionmaker())
class User(Base):
   __tablename__ = 'users'

   id = Column(Integer, primary_key=True)
   name = Column(String)
   fullname = Column(String)
   password = Column(String)
session = Session()
print(User.query)

该代码失败并出现以下错误:

AttributeError:类型对象“用户”没有属性“查询”

你需要做这样的事情:

class User(Base):
   __tablename__ = 'users'

   id = Column(Integer, primary_key=True)
   name = Column(String)
   fullname = Column(String)
   password = Column(String)
   query = DBSession.query_property()

但是,也有人认为,仅仅因为默认情况下未启用它,这并不会使它作为启动查询的合理方式无效。此外,在 flask-sqlalchemy 包(它简化了 sqlalchemy 与 flask web 框架的集成)中,这已经作为模型类(doc) 的一部分为您完成了。在 sqlalchemy 教程(doc) 中也可以看到将查询属性添加到模型中:

class User(object):
   query = db_session.query_property()
   ....

因此,人们可以争论任何一种方法。

当我从单个表中选择时,我个人更喜欢第二种方法。例如:

serv = Service.query.join(Supplier, SupplierUsr).filter(SupplierUsr.username == usr).all()

这是因为它的行长度更短,并且仍然易于阅读。

如果要从多个表中选择或指定列,那么我会使用模型查询方法,因为它从多个模型中提取信息。

deliverables = db.session.query(Deliverable.column1, BatchInstance.column2).\
    join(BatchInstance, Service, Supplier, SupplierUser). \
    filter(SupplierUser.username == str(current_user)).\
    order_by(Deliverable.created_time.desc()).all()

也就是说,可以在始终使用 session.query 方法时进行反参数,因为它使代码更加一致,并且当从左到右阅读时,读者立即知道他们将要阅读的 sqlalchemy 指令将是查询,在精神吸收涉及哪些表和列之前。

归根结底,您的问题的答案是主观的,没有正确答案,任何一种代码可读性的好处都是微乎其微的。如果您从许多表中进行选择,我认为唯一的好处是不要使用模型查询,而是使用 session.query 方法。

【讨论】:

  • 不过,你会如何混合两者呢?我的意思是,Model.query 使用 DBSession,只实例化一次,例如 DBSession = scoped_session(SessionLocal)。但是我在 BaseMixin 中也有辅助方法(插入、更新、删除),但在这种情况下,会话是一个参数,所以我必须创建一个新的。因此,如果通过Model.query 进行查询并尝试使用我的辅助方法,它会中断,因为该对象已经分配给另一个会话。有什么想法吗?
猜你喜欢
  • 2017-02-22
  • 1970-01-01
  • 2012-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
相关资源
最近更新 更多