Как сделать неравное в фильтрации наборов запросов Django? - PullRequest
570 голосов
/ 26 марта 2009

В модели QuerySets 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)

Ответы [ 14 ]

593 голосов
/ 20 июля 2009

Может быть 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>, ...]
522 голосов
/ 10 ноября 2010

Ваш запрос, по-видимому, имеет двойной минус, вы хотите исключить все строки, где x не равно 5, то есть, другими словами, вы хотите включить все строки, где x IS 5. Я считаю, что это поможет.

results = Model.objects.filter(x=5).exclude(a=true)

Чтобы ответить на ваш конкретный вопрос, нет «не равно», но это, вероятно, потому, что в django есть методы «filter» и «exclude», так что вы всегда можете просто переключить логику, чтобы получить желаемый результат.

111 голосов
/ 20 июля 2009

синтаксис 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() как Джейсон Бейкер предлагает вы получите именно то, что вы нужен практически для любого возможного запроса.

85 голосов
/ 24 марта 2015

С Django 1.7 легко создать пользовательский поиск. В официальной документации Django .

есть пример поиска __ne.

Сначала вам нужно создать сам поиск:

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)
76 голосов
/ 24 февраля 2016

В Джанго 1,9 / 1,10 есть три варианта.

  1. Цепь exclude и filter

    results = Model.objects.exclude(a=true).filter(x=5)
    
  2. Использование Q() объектов и оператора ~

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
    
  3. Регистрация пользовательской функции поиска

    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 был добавлен в Django 1.8 и разрешает пользовательский поиск как обычно:

    results = Model.objects.exclude(a=True, x__ne=5)
    
39 голосов
/ 18 января 2011

При использовании моделей вы можете фильтровать с помощью =, __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')
18 голосов
/ 21 апреля 2016

В ожидании проектного решения. Между тем, используйте exclude()

Система отслеживания проблем Django имеет замечательную запись # 5763 , "В Queryset отсутствует оператор фильтра" Не равно "" . Это замечательно, потому что (по состоянию на апрель 2016 года) «Открыт 9 лет назад» (в каменном веке Джанго), "закрыто 4 года назад", и "Последнее изменение 5 месяцев назад".

Прочитайте обсуждение, это интересно. В основном, некоторые люди утверждают, что __ne следует добавить в то время как другие говорят, что exclude() яснее и, следовательно, __ne следует добавить , а не .

(Я согласен с первым, потому что последний аргумент примерно эквивалентно тому, что Python не должен иметь !=, потому что == и not уже ...)

14 голосов
/ 25 сентября 2015

Вы должны использовать filter и exclude, как это

results = Model.objects.exclude(a=true).filter(x=5)
11 голосов
/ 12 июля 2018

Использование исключений и фильтров

results = Model.objects.filter(x=5).exclude(a=true)
8 голосов
/ 26 марта 2009

Последний бит кода исключит все объекты, где x! = 5 и a - True. Попробуйте это:

results = Model.objects.filter(a=False, x=5)

Помните, что знак = в приведенной выше строке обозначает False для параметра a, а номер 5 - для параметра x. Это не проверка на равенство. Таким образом, на самом деле нет никакого способа использовать символ! = В вызове запроса.

...