主题可能有点模糊,因此这里是一个示例。假设我有一个模型:
class TestModel(models.Model):
user = models.ForeignKey(User, ...)
我想要一个包含has_user
字段的QuerySet,该字段基本上将映射到以下SQL查询
select *, user_id is not null as has_user
from app_testmodel
使用has_user
时如何向Django解释此QuerySet.annotate
字段?
我知道Django具有models.F
,models.Q
,models.lookups
,models.expressions
等概念,但是我无法理解如何在我的情况下应用它们。据我所知,这是将“查找”转换为布尔“表达式”的问题,其中
在Django ORM语言中,“查找”类似于'user_id__isnull'
或lookups.IsNull(models.F('user_id'))
。
“表达式”类似于expressions.ExpressionWrapper(?, output_field=models.BooleanField())
。
到目前为止,我仅设法将user_id is not null
表达式转换为case when user_id is not null then true else false end
,该表达式映射为如下的Python代码:
from django.db import models
from django.db.models import expressions
# ...
qs = TestModel.objects.all().annotate(has_user=
expressions.Case(
expressions.When(
user__isnull=False,
then=expressions.Value(True),
),
default=expressions.Value(False),
#
# Tell Django the expected type of the field, see `output_field` in
# https://docs.djangoproject.com/en/2.1/ref/models/expressions/
#
output_field=models.BooleanField()))
但这是一个尴尬的解决方法。必须有一个更好的解决方案:更合适,更轻松,更清洁到Python代码以及生成的SQL查询。
答案 0 :(得分:0)
关键是使用models.Q
和expressions.ExpressionWrapper
:
qs = TestModel.objects.all().annotate(
has_user=expressions.ExpressionWrapper(
models.Q(user_id__isnull=False),
output_field=models.BooleanField()
)
)