Django ORM中F表达式的逻辑或

时间:2019-06-06 01:41:50

标签: django postgresql sqlite orm

我有一个类似的查询

User.objects.annotate(
    x=Value(False, output_field=BooleanField()),
    y=Value(True, output_field=BooleanField())
).annotate(
    z=F('x').bitor(F('y'))  # HOW TO DO THIS?
).values('z')

可用于SQLite,但不适用于PostgreSQL。错误是

LINE 1: SELECT (false | true) AS "z" FROM "auth_user"  LIMIT 21
                      ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.

我应该如何在始终有效的带注释字段上实现逻辑或?

谢谢。

2 个答案:

答案 0 :(得分:2)

Django 本身不为 Expression 对象提供逻辑运算符,而是在更深入的框架中,ValueF 都继承自 Combinable 类。这个类实际上为我们提供了我们可以使用的运算符,不幸的是不是布尔运算符。

如果我们的两个值都可以解析为表达式(Values 是),我们可以自己将运算符传递给数据库。为此,我们将完全按照 Combinable 执行的操作 - 初始化 CombinedExpression 对象:

User.objects.annotate(
        x=Value(False, output_field=BooleanField()),
        y=Value(True, output_field=BooleanField())
    ).annotate(
        z=CombinedExpression(lhs=F('x'), rhs=F('y'), connector="OR")
    ).values('z')

此解决方案可能不兼容所有数据库,但适用于 PostgreSQL。

答案 1 :(得分:1)

使用按位运算符将其转换为整数类型

from django.db.models.functions import Cast

User.objects.annotate(
    x=Value(False, output_field=BooleanField()),
    y=Value(True, output_field=BooleanField())
).annotate(
    z=Cast(Cast(F('x'), IntergerField()).bitor(Cast(F('y'), IntergerField())), BooleanField())
).values('z')