我的User
模型的主键位于user_id
,唯一username
。如果我知道user_id
,我会使用session.query(User).get(user_id)
。当属性不是主键时,等效查询是什么,如session.query(User).get(username=username)
?
session.query(User).filter_by(username=username).first()
也会返回None
,但它没有明确表示该查询永远不会有多行。
我写了以下内容,但这是否是任何人在其代码中常规实现的帮助?
try:
user = session.query(User).filter_by(username=username).one()
except (NoResultFound, MultipleResultsFound):
user = None
答案 0 :(得分:1)
"惯用"查询一件事的方法是使用filter
和first
或one
,get
基本上只是主键的快捷方式。如果您要问的是"这个尝试/接受块是否可以使用"然后是的,它会正常工作,没有人会觉得难以理解。
有点令人困惑的是,如果有多个结果,则会返回None
,但如果这就是你需要的那么可行。鉴于username
列已经具有唯一约束,无论如何这种方法都是无用的,因为用户名永远不会有多个结果。
更强大的可重用解决方案是使用自定义Query
子类并添加行为与one
类似的one_or_none
方法。创建会话时,通过传递query_cls
使其使用此类。
from sqlalchemy.orm import Query
class MyQuery(Query):
def one_or_none(self):
"""Return one result, or None if there are zero or >1 results."""
ret = self.limit(2).all()
if len(ret) == 1:
return ret[0]
else:
return None
session = Session(query_cls=MyQuery)
session.query(User).filter(username="example").one_or_none()
同样,当有多个结果时返回None并不是典型的行为,并且当它有一个独特的约束时,它并没有真正做任何事情。
如果这是一项常见操作,您还可以添加一个特定的方法来按用户名进行查询。来自this gist的user Adam Smith修改:
from sqlalchemy.orm import Query
from sqlalchemy.orm.exc import MultipleResultsFound
class MyQuery(Query):
def get_by_username(self, username):
ret = self.filter(username=username).limit(2).all()
if len(ret) == 1:
return ret[0]
else:
return None
session = Session(query_cls=MyQuery)
session.query(User).get_by_username("example")