Peewee中的NOT IN操作符

16 投票
3 回答
7490 浏览
提问于 2025-04-20 13:44

文档里有说明如何使用 IN 操作符,但是我找不到如何使用 NOT IN 操作符的方法。

如果我用 not <<,就会出现语法错误。

如果我用 not <FieldName> <<,结果会变成 WHERE False,而不是像 WHERE (<FieldName> NOT IN (SELECT ... 这样的子查询。

这是根据文档示例得到的输出。第一个是正确的,第二个和第三个都是错误的。

>>> Tweet.select().where(Tweet.user << a_users).sql()
('SELECT t1."id", t1."user_id", t1."message", t1."created_date", t1."is_published" FROM "tweet" AS t1 WHERE (t1."user_id" IN (SELECT t2."id" FROM "user" AS t2 WHERE (Lower(Substr(t2."username", ?, ?)) = ?)))', [1, 1, 'a'])
>>> Tweet.select().where(not Tweet.user << a_users).sql()
('SELECT t1."id", t1."user_id", t1."message", t1."created_date", t1."is_published" FROM "tweet" AS t1 WHERE ?', [False])
>>> Tweet.select().where(Tweet.user not << a_users).sql()
SyntaxError: invalid syntax

3 个回答

1

这其实和Peewee没什么关系。Peewee只是用了一些Python的运算符来实现自己的功能。<<通常是一个数字运算符,给它加上逻辑否定是没有意义的。所以not <<在Python中是无效的语法。

你的第二个例子差不多,但not只作用于Tweet.user(因为not的优先级比<<高)。加上一些括号,你可以这样写:

Tweet.select().where(not (Tweet.user << a_users)).sql()

不过这仍然不对,正如你发现的那样(读者们:可以看看评论区的讨论)。not返回的是一个布尔值,这并不是我们想要的,无法正常工作。Peewee把~运算符重新用来做这个;可以看看@coleifer的回答。

4

我知道这算是“复活帖”,不过这个问题在谷歌上搜索 peewee not in 时是第一个结果,所以我想在这里补充一下:

你还可以使用 not_in 方法,这在文档中有说明:

Tweet.select().where(Tweet.user.not_in(a_users))

对我来说,这种写法比 ~ ... << 这种写法要清晰很多。

33

简单来说:

Tweet.select().where(Tweet.user.not_in(a_users))

如果你想要稍微不同的意思,比如说“x 不在 y 中”,而不是“x 不在 y 里”,可以用下面的方式:

Tweet.select().where(~(Tweet.user << a_users))

撰写回答