Найти - Пользователи
Полная версия: ORM: date__range и непонятный NOT NULL
Начало » Django » ORM: date__range и непонятный NOT NULL
1
int_0x80
Имеем следующие две модели:
from django.db import models
class ModelA(models.Model):
    date = models.DateTimeField(null=True, default=None)
class ModelB(models.Model):
    a = models.OneToOneField(ModelA, related_name='modela')

И нужно отфильтровать данные, не входящих в определенный диапазон date. Так и пишем:
ModelB.objects.select_related().exclude(Q(a__date__range=('2010-01-01', '2014-01-01')))
Получаем SQL запрос:
SELECT "temp_modelb"."id", "temp_modelb"."a_id", "temp_modela"."id", "temp_modela"."date" FROM "temp_modelb" INNER JOIN "temp_modela" ON ( "temp_modelb"."a_id" = "temp_modela"."id" ) WHERE NOT ("temp_modela"."date" BETWEEN '2010-01-01 00:00:00+00:00' and '2014-01-01 00:00:00+00:00' AND "temp_modela"."date" IS NOT NULL) LIMIT 21

Вопрос в том, откуда взялось условие:
AND "temp_modela"."date" IS NOT NULL

Выяснил, что это условие подставляется, если у поля выставлен флаг null=True.
Как избавится от этого условия не прибегая к raw sql?
terabayt
isnull
Takes either True or False, which correspond to SQL queries of IS NULL and IS NOT NULL, respectively.
Example:
Entry.objects.filter(pub_date__isnull=True)
SQL equivalent:
SELECT ... WHERE pub_date IS NULL;

int_0x80
terabayt, я знаю, что такое isnull. Вопрос не в этом.
terabayt
Тогда в чем? Объясните непосвященному))
наведите пример, что вы хотите получить и что вас не устраивает.
int_0x80
Вот при такой выборке:
ModelB.objects.select_related().exclude(Q(a__date__range=('2010-01-01', '2014-01-01')))
Генерируется такой SQL запрос:
SELECT "temp_modelb"."id", "temp_modelb"."a_id", "temp_modela"."id", "temp_modela"."date" FROM "temp_modelb" INNER JOIN "temp_modela" ON ( "temp_modelb"."a_id" = "temp_modela"."id" ) WHERE NOT ("temp_modela"."date" BETWEEN '2010-01-01 00:00:00+00:00' and '2014-01-01 00:00:00+00:00' AND "temp_modela"."date" IS NOT NULL)

Вопрос: откуда взялось условие
AND "temp_modela"."date" IS NOT NULL
Ведь я этого не указывал.
Второй вопрос, как избавиться от этого условия.
terabayt
int_0x80
Ведь я этого не указывал.
а как же
null=True
этим вы указали что может быть пустая запись. и поэтому добавляется новая проверка. если бы null=False, то не было бы смысла проверять то, что невозможно записать!
Зачем вам избавляться от этого условия?
int_0x80
А почему тогда если применить вместо exclude - filter, то это условие не вставляется?
ModelB.objects.select_related().filter(Q(a__date__range=('2010-01-01', '2014-01-01')))

SELECT "temp_modelb"."id", "temp_modelb"."a_id", "temp_modela"."id", "temp_modela"."date" FROM "temp_modelb" INNER JOIN "temp_modela" ON ( "temp_modelb"."a_id" = "temp_modela"."id" ) WHERE "temp_modela"."date" BETWEEN '2010-01-01 00:00:00+00:00' and '2014-01-01 00:00:00+00:00'
terabayt
Может нужно основы дискретной математики почитать?!
при exclude используется “если не в диапазоне, то катит”, а в filter “если в диапазоне, то катит”. а так как вы написали null=True, то и пустые значения удовлетворяют. если будет null=False, то тогда уже будет отсеиватся, тоесть будет
 ... WHERE ("temp_modela"."date" BETWEEN '2010-01-01 00:00:00+00:00' and '2014-01-01 00:00:00+00:00' AND "temp_modela"."date" IS NOT NULL)
FishHook
.exclude(Q(a__date__range=('2010-01-01', '2014-01-01')))
А на кой чёрт тут Q?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB