Уведомления

Группа в Telegram: @pythonsu

#1 Июль 14, 2014 12:16:48

int_0x80
Зарегистрирован: 2012-09-27
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

Имеем следующие две модели:

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?

Офлайн

#2 Июль 14, 2014 13:43:22

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

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;



————————————————
-*- Simple is better than complex -*-

Офлайн

#3 Июль 14, 2014 17:50:56

int_0x80
Зарегистрирован: 2012-09-27
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

terabayt, я знаю, что такое isnull. Вопрос не в этом.

Офлайн

#4 Июль 14, 2014 18:31:34

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

Тогда в чем? Объясните непосвященному))
наведите пример, что вы хотите получить и что вас не устраивает.



————————————————
-*- Simple is better than complex -*-

Офлайн

#5 Июль 14, 2014 19:26:01

int_0x80
Зарегистрирован: 2012-09-27
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

Вот при такой выборке:

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
Ведь я этого не указывал.
Второй вопрос, как избавиться от этого условия.

Отредактировано int_0x80 (Июль 14, 2014 19:27:22)

Офлайн

#6 Июль 14, 2014 20:13:54

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

int_0x80
Ведь я этого не указывал.
а как же
null=True
этим вы указали что может быть пустая запись. и поэтому добавляется новая проверка. если бы null=False, то не было бы смысла проверять то, что невозможно записать!
Зачем вам избавляться от этого условия?



————————————————
-*- Simple is better than complex -*-

Отредактировано terabayt (Июль 14, 2014 20:15:07)

Офлайн

#7 Июль 14, 2014 20:48:14

int_0x80
Зарегистрирован: 2012-09-27
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

А почему тогда если применить вместо 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'

Офлайн

#8 Июль 14, 2014 21:18:03

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

Может нужно основы дискретной математики почитать?!
при 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)



————————————————
-*- Simple is better than complex -*-

Офлайн

#9 Июль 15, 2014 05:29:23

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

ORM: date__range и непонятный NOT NULL

.exclude(Q(a__date__range=('2010-01-01', '2014-01-01')))
А на кой чёрт тут Q?



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version