Как мне выполнить фильтрацию not equal в наборе запросов Django?
-
22-08-2019 - |
Вопрос
В наборах запросов модели Django я вижу, что есть __gt
и __lt
для сравнительных значений, но есть ли __ne
/!=
/<>
(не равны?)
Я хочу отфильтровать, используя не равно:
Пример:
Model:
bool a;
int x;
Я хочу
results = Model.objects.exclude(a=true, x!=5)
В !=
это неправильный синтаксис.Я пытался __ne
, <>
.
В итоге я использовал:
results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
Решение
Может быть Q объекты могло бы помочь в решении этой проблемы.Я никогда не использовал их, но, похоже, их можно отрицать и комбинировать так же, как обычные выражения python.
Обновить:Я только что опробовал это, кажется, это работает довольно хорошо:
>>> from myapp.models import Entry
>>> from django.db.models import Q
>>> Entry.objects.filter(~Q(id = 3))
[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]
Другие советы
Похоже, что ваш запрос имеет двойное отрицание, вы хотите исключить все строки, где x не равно 5, другими словами, вы хотите включить все строки, где x РАВНО 5.Я верю, что это сработает.
results = Model.objects.filter(x=5).exclude(a=true)
Чтобы ответить на ваш конкретный вопрос, нет "не равно", но это, вероятно, потому, что в django доступны как методы "filter", так и "exclude", так что вы всегда можете просто переключить логический цикл, чтобы получить желаемый результат.
в field=value
синтаксис в запросах - это сокращение для field__exact=value
.То есть нужно сказать , что Django помещает операторы запроса в поля запроса в идентификаторах.Django поддерживает следующие операторы:
exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex
Я уверен, что, объединив их с объектами Q как Дэйв Вогт предлагает и используя filter()
или exclude()
как Джейсон Бейкер предлагает вы получите именно то, что вам нужно практически для любого возможного запроса.
С помощью Django 1.7 легко создать пользовательский поиск.Там есть __ne
пример поиска в Официальная документация Django.
Сначала вам нужно создать сам поиск:
from django.db.models import Lookup
class NotEqual(Lookup):
lookup_name = 'ne'
def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return '%s <> %s' % (lhs, rhs), params
Затем вам нужно его зарегистрировать:
from django.db.models.fields import Field
Field.register_lookup(NotEqual)
И теперь вы можете использовать __ne
выполняйте поиск в ваших запросах следующим образом:
results = Model.objects.exclude(a=True, x__ne=5)
В Джанго 1.9/1.10 есть три варианта.
-
results = Model.objects.exclude(a=true).filter(x=5)
Использование
Q()
Объекты и тот~
операторfrom django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
Зарегистрировать a пользовательская функция поиска
from django.db.models import Lookup from django.db.models.fields import Field @Field.register_lookup class NotEqual(Lookup): lookup_name = 'ne' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) params = lhs_params + rhs_params return '%s <> %s' % (lhs, rhs), params
В
register_lookup
декоратор был добавлен в Джанго 1.8 и включает пользовательский поиск как обычно:results = Model.objects.exclude(a=True, x__ne=5)
В то время как с моделями вы можете фильтровать с =
, __gt
, __gte
, __lt
, __lte
, вы не можете использовать ne
, !=
или <>
.Однако вы можете добиться лучшей фильтрации при использовании объекта Q.
Вы можете избежать цепочки QuerySet.filter()
и QuerySet.exlude()
, и используйте это:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
Ожидающее принятия проектного решения.Тем временем, используйте exclude()
Средство отслеживания проблем Django обладает замечательными запись №5763, под названием "В наборе запросов нет оператора фильтра "не равно"".Это примечательно, потому что (по состоянию на апрель 2016 года) это было "открыто 9 лет назад" (в каменном веке Джанго), "закрыто 4 года назад" и "последнее изменение 5 месяцев назад".
Прочтите обсуждение, это интересно.В принципе, некоторые люди спорят __ne
следует добавить
в то время как другие говорят exclude()
яснее и, следовательно, __ne
следует не быть добавленным.
(Я согласен с первым, потому что последний аргумент
примерно эквивалентен высказыванию, что Python не должен иметь !=
потому что
это имеет ==
и not
уже...)
Вы должны использовать filter
и exclude
вот так
results = Model.objects.exclude(a=true).filter(x=5)
Использование исключения и фильтрации
results = Model.objects.filter(x=5).exclude(a=true)
Последний бит кода исключит все объекты, где x!=5 и a равно True.Попробуй это:
results = Model.objects.filter(a=False, x=5)
Помните, что знак = в приведенной выше строке присваивает параметру a значение False, а параметру x - число 5.Это не проверка на равенство.Таким образом, на самом деле нет никакого способа использовать символ != в вызове запроса.
То, что вы ищете, - это все объекты, которые имеют либо a=false
или x=5
.В Джанго, |
служит в качестве OR
оператор между наборами запросов:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)Генерирует этот sql:
select * from tablex where a != 0 and x !=5sql зависит от того, как представлено ваше поле True / False, и от компонента database engine.Однако код django - это все, что вам нужно.
Django-модель-значения (раскрытие:автор) обеспечивает реализацию Не равный поиск, как в этот ответ.Он также предоставляет для него синтаксическую поддержку:
from model_values import F
Model.objects.exclude(F.x != 5, a=True)
Следите за множеством неправильных ответов на этот вопрос!
Логика Джерарда верна, хотя она вернет список, а не набор запросов (что может не иметь значения).
Если вам нужен набор запросов, используйте Q:
from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))