Тема может быть немного неясной, поэтому вот пример. Допустим, у меня есть модель:
class TestModel(models.Model):
user = models.ForeignKey(User, ...)
Мне нужен QuerySet, содержащий поле has_user
, которое в основном соответствовало бы следующему SQL-запросу
select *, user_id is not null as has_user
from app_testmodel
Как я могу объяснить это has_user
поле Django при использовании QuerySet.annotate
?
Мне известно, что у Джанго есть такие понятия, как models.F
, models.Q
, models.lookups
, models.expressions
и т. Д., Но я не могу понять, как применять их в моем случае. Насколько мне известно, это вопрос преобразования слова «поиск» в логическое «выражение», где
«Поиск» - это что-то вроде 'user_id__isnull'
или lookups.IsNull(models.F('user_id'))
на языке Django ORM.
«Выражение» - это что-то вроде 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-запрос.