2017-02-21 36 views
0

Я пытаюсь найти все экземпляры одной из моих моделей, у которой есть атрибут, установленный либо None, либо пустая строка. Я думаю, что мне не хватает чего-то в запросе ORM __in.Непоследовательные результаты запроса ORM Django с «Q» против «__in»

TextBlock.objects.filter(content='').count() 
>185 
TextBlock.objects.filter(content=None).count() 
>235 
TextBlock.objects.filter(content__in=['', None]).count() 
>185 
TextBlock.objects.filter(Q(content='')|Q(content=None)).count() 
>420 
TextBlock.objects.filter(content__in=[None, '']).count() 
>185 

Когда я делаю это с IntegerFIeld и не используя None или пустые строки, я получаю:

TextBlock.objects.filter(order=1).count() 
> 575046 
TextBlock.objects.filter(order=2).count() 
> 11946 
TextBlock.objects.filter(order__in=[1,2]).count() 
> 586992 

Это то, что я ожидал. Был ли я неправ, чтобы ожидать TextBlock.objects.filter(content__in=['', None]).count(), чтобы вернуть 420 результатов? Если да, то почему?

Q-запрос делает то, что я хочу, поэтому я закончу с этим, но мне все еще интересно, почему этот третий запрос не сделал то, что я хотел.

Спасибо!

EDIT: Не уверен, если это имеет значение, но поле контента является models.TextField и поле порядка является models.IntegerField

ответ

2

Обратите внимание, что NULL == NULL на самом деле неверно в SQL, и вам нужно использовать IS NULL, чтобы проверить, является ли значение нулевым. Django достаточно умен, чтобы преобразовать Q(content=None) в оператор IS NULL, поэтому TextBlock.objects.filter(Q(content='')|Q(content=None)).count() возвращает ожидаемые результаты.

Оператор IN может сравнивать только его элементы, он не может выполнить проверку IS NULL. Чтобы проверить нулевые значения, вам необходимо явно добавить content=None или эквивалент content__isnull=True.

Запрос с использованием __in должен работать как ожидалось для любого списка значений, который не включает NULL.

0

Для проверки, если содержимое не является None, вы не должны использовать сравнение. Вы должны использовать content__isnull в ОРМ (и вы можете объединить запросы с объектом Q, как вы делаете)

0

Вы проверяете для None значений с помощью isnull поля поиска:

TextBlock.objects.filter(Q(content='')|Q(content__isnull=True)).count()