使用Peewee检查查询是否存在

15

我正在使用Python中的Peewee库,并希望检查查询是否存在。如果不存在,我不想创建记录,因此不想使用get_or_create。一定有比使用try / except与get更好的解决方案,但我没有看到任何东西。如果有更好的方法,请告诉我。谢谢。

我正在使用Python的Peewee库,想要检查一个查询是否存在。我不想使用get_or_create来创建记录,而是想要一个更好的解决方案。我不想在查询不存在时创建一个新记录。除了使用try/except和get之外,还有没有更好的方法呢?如果有,请告诉我。谢谢。

使用try/except方法有什么问题吗? - taesu
看起来不太优雅。 - calthoff
3个回答

43

如果我正在使用db.atomic()作为单个事务的一部分来“获取或创建”多个相关条目(即不是针对每个条目使用函数get_or_create()),在您看来,使用try/except还是exists()更好? - ron_g

18

如果你只需要检查是否存在,使用已接受的答案即可。

如果你要在记录存在时使用它,可以使用Model.get_or_none(),因为它不需要使用try/catch,并且如果该记录不存在,它不会创建新记录。

class User(peewee.Model):
    username = peewee.CharField(unique=True)

user = User.get_or_none(username='charlie')
if user is not None:
    # found user, do something with it
    pass

2
我对这些踩票感到惊讶,所以我澄清了我的回答。我阅读问题的理解是,如果对象存在,他们想要做某些事情。这也是我在遇到这个问题时所拥有的问题。 - Weston

3

或者,如果你想检查其他表是否引用了这条记录,可以使用 WHERE EXISTS (subquery) 子句。PeeWee 不支持原生的构造方式,但它可以很容易地构建:

subquery = Child.select(Param('1')).where(Child.parent == Parent.id)
parents_with_children = Parent.select().where(
    Clause(SQL('EXISTS'), subquery))

这相当于以下SQL:

SELECT * FROM parent
WHERE EXISTS (SELECT 1 FROM child
              WHERE child.parent_id = parent.id);

我在子查询中使用SELECT 1以避免获取不需要的信息(比如child.id)。不确定是否实际需要这样的优化。

更新 (2022年2月)

经过5年多的peewee发展,看起来Clause类已经被移除了。

下面的代码可能可以工作(虽然我没有测试过):

subquery = Child.select(Param('1')).where(Child.parent == Parent.id)
parents_with_children = Parent.select().where(
    NodeList((SQL('EXISTS'), subquery)))

你是从哪里导入 Clause 的?我在 peewee 源代码中找不到它。 - Matthew Moisen
1
请注意,此答案已经超过5年了。看起来自那时以来Clause已被删除或重命名。 您可能会发现这个链接有用:https://github.com/coleifer/peewee/commit/2f0b3 - 这是最新的提交之一,提到Clause类已过时并提出了替代方案。 - MarSoft
1
我偶然发现以下代码似乎可以工作:Parent.select().where(fn.EXISTS(subquery))。Peewee似乎很聪明,你甚至不需要在子查询中使用Param('1')。因此,当在exists中使用时,subquery = Child.select().where(Child.parent == Parent.id)实际上会变成一个select 1,原因不详。 - Matthew Moisen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接