Django queryset filtrelemede nasıl eşit değilim?


664

Django modeli QuerySets, ben bir __gtve __ltkarşılaştırma değerleri olduğunu görüyorum , ama bir __ne/ !=/ <>( eşit değil ?)

Eşit değil kullanarak filtre uygulamak istiyorum:

Misal:

Model:
    bool a;
    int x;

İstiyorum

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

!=Doğru sözdizimi değil. Denedim __ne, <>.

Ben kullanarak sona erdi:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)

75
Results = Model.objects.exclude (a = true) .filter (x = 5) işe yarar mı?
hughdbrown

3
@hughdbrown. Hayır. Sorgunuz a=trueönce tümünü hariç tutar ve ardından x=5kalan filtreyi uygular . Amaçlanan sorgu yalnızca a=trueve olanları gerektiriyordu x!=5. Aradaki fark, a=trueve x=5olanların da filtrelenmesidir.
Mitchell van Zuylen

Yanıtlar:


690

Belki Q nesneleri bu sorun için yardımcı olabilir. Onları hiç kullanmadım ama normal python ifadeleri gibi reddedilebilir ve birleştirilebilirler.

Güncelleme: Sadece denedim, oldukça iyi çalışıyor gibi görünüyor:

>>> 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>, ...]

16
@ JCLeitão: Daha sezgisel sözdizimi için aşağıdaki @ d4nt'nin cevabına da bakınız .
Paul D.Waite

610

Sorgunuzun çift negatif olduğu görülüyor, x'in 5 olmadığı tüm satırları hariç tutmak istiyorsunuz, yani x x 5'in olduğu tüm satırları dahil etmek istiyorsunuz. Bunun hile yapacağına inanıyorum.

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

Belirli bir sorunuzu cevaplamak için "eşit değil" yoktur, ancak bunun nedeni muhtemelen django'nun hem "filtre" hem de "hariç tutma" yöntemlerinin bulunmasıdır, böylece istediğiniz sonucu elde etmek için her zaman mantık turunu değiştirebilirsiniz.


2
@ d4nt: Yanlış olabilirim, ama sanırım sorgu olmalıresults = Model.objects.filter(a=true).exclude(x=5)
Taranjeet

1
@Taranjeet: Bence orijinal sorguyu yanlış okudun. d4nt'nin sürümü doğrudur, çünkü OP x = 5'in hariç tutulması (a = True) ve hariç tutulmasını reddetmek istemiştir (yani dahil et).
Chuck

3
Bunun yanlış olduğunu düşünüyorum çünkü bir örnek (x = 4, a = false) yanlış hariç tutulur.
RemcoGerlich

4
@danigosa Bu doğru görünmüyor. Bunu kendim denedim ve sırası excludeve filterçağrıları anlamlı bir fark yaratmadı. WHEREŞarttaki koşulların sırası değişir, ancak bunun önemi nedir?
coredumperror

4
@ danigosa hariç tutma ve filtre sırası önemli değil.
EralpB

132

field=valuesorgularda sözdizimi için bir kısaltmadır field__exact=value. Yani Django, sorgu operatörlerini tanımlayıcılardaki sorgu alanlarına koyar . Django aşağıdaki operatörleri destekler:

exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex

Dave Vogt'ın önerdiği ve Q Baker ile birleştirerek filter()veya Jason Baker'ın önerdiğiexclude() gibi , olası herhangi bir sorgu için tam olarak ihtiyacınız olanı alacağınızdan eminim.


teşekkürler bu harika. böyle bir şey kullandım tg=Tag.objects.filter(user=request.user).exclude(name__regex=r'^(public|url)$')ve işe yarıyor.
suhailvs

@suhail, lütfen tüm veritabanlarının normal ifade sözdizimini desteklemediğini unutmayın :)
Anoyz

2
i icontains, iexactve "küçük harf duyarlılığı göz ardı" için benzer duruyor. "Ters" için değildir.
Ivy

exclude()Birden çok terimle kullandığınızda OR, örneğin exclude(Q(field1__queryop1=value1) | Q(field2__queryop2=value2))her iki koşulda da sonuçları hariç tutmak için teklifi operatörle birlikte oluşturmak isteyebilirsiniz .
clapas

98

Django 1.7 ile özel bir arama oluşturmak kolaydır. Django resmi belgelerinde bir __nearama örneği var .

Önce aramanın kendisini oluşturmanız gerekir:

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

Sonra kaydetmeniz gerekir:

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

Ve şimdi __nesorgunuzda aramayı şu şekilde kullanabilirsiniz :

results = Model.objects.exclude(a=True, x__ne=5)

88

In Django 1.9 / 1.10 üç seçenek vardır.

  1. Zincir excludevefilter

    results = Model.objects.exclude(a=true).filter(x=5)
  2. Kullanım Q()nesneleri ve ~operatör

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
    
  3. Bir Kayıt özel arama fonksiyonunu

    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_lookupDekoratör ilave edildi Django 1.8 ve özel zamanki gibi arama etkinleştirir:

    results = Model.objects.exclude(a=True, x__ne=5)

1
object_list = QuerySet.filter (~ Q (a = True), x = 5): Q içermeyen diğer tüm koşulları, Q içerenlerden sonra tutmayı unutmayın.
Bhumi Singhal

1
@MichaelHoffmann: A) ~ Q kullanarak hariç tutulduktan sonra daha küçük bir veri kümesine filtre uygulayacağınız için daha verimlidir. B) muhtemelen dizilim başka bir şekilde çalışmaz .. dun biliyorum .. dun unutmayın!
Bhumi Singhal

41

Modeller, sen ile filtre ederken =, __gt, __gte, __lt, __lte, kullanmak olamaz ne, !=ya da <>. Ancak, Q nesnesini kullanarak daha iyi filtreleme elde edebilirsiniz.

Sen zincirleme önleyebilirsiniz QuerySet.filter()ve QuerySet.exlude()ve bu kullanın:

from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')

24

Bekleyen tasarım kararı. Bu arada,exclude()

Django sorun izleyicide "Queryset'in" eşit olmayan bir "filtre operatörü yok" başlıklı # 5763 numaralı giriş bulunmaktadır . Bu dikkat çekicidir (Nisan 2016 itibariyle) "9 yıl önce açıldı" (Django taş çağında), "4 yıl önce kapatıldı" ve "son 5 ay önce değişti".

Tartışmayı okuyun, ilginç. Temel olarak, bazı insanlar iddia __nediğerleri söylerken eklenmelidir exclude()nettir ve dolayısıyla __ne gerektiği değil eklenebilir.

(Birincisine katılıyorum, çünkü son argüman Python'un sahip !=olması gerektiği için söylememesi kabaca eşdeğerdir ==ve notzaten ...)


22

Hariç tut ve filtrele özelliğini kullanma

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

18

Bunu kullanmalı filterve excludebeğenmelisin

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

8

Kodun son biti, x! = 5 ve a'nın True olduğu tüm nesneleri hariç tutacaktır. Bunu dene:

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

Unutmayın, yukarıdaki satırdaki = işareti a parametresine False ve x parametresine 5 sayısını atar. Eşitliği kontrol etmiyor. Bu nedenle, bir sorgu çağrısında! = Sembolünü kullanmanın gerçekten bir yolu yoktur.


3
Bu alanlar için de Null değerler olabileceğinden, bu% 100 aynı şey değildir.
MikeN

Bu yalnızca a = False ve x = 5 olan öğelerde döndürülür , ancak soruda bir örnek (a = false, x = 4) eklenir.
RemcoGerlich

1
results = Model.objects.filter(a__in=[False,None],x=5)
Jeremy

8

results = Model.objects.filter (a = Doğru). hariç (x = 5)
Bu sql üretir:
tablex'ten * seçin; burada a! = 0 ve x! = 5
SQL, Doğru / Yanlış alanınızın nasıl temsil edildiğine ve veritabanı motoruna bağlıdır. Django kodu olsa gerek.



6

Aradığın şey ya a=false ya olan tüm nesnelerdir x=5. Django'da, sorgu kümeleri arasında operatör |görevi görür OR:

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)

5

Bu istediğiniz sonucu verecektir.

from django.db.models import Q
results = Model.objects.exclude(Q(a=True) & ~Q(x=5))

için değil eşit kullanabileceğiniz ~eşit sorguyu. Açıkçası, Qeşit sorguya ulaşmak için kullanılabilir.


Lütfen düzenlemeyi kontrol edin; “ve” in kullanılması argüman olarak Q(a=True) and ~Q(x=5)değerlendirilir . Lütfen şunu okuyun: docs.python.org/3/reference/expressions.html#boolean-operations ve docs.python.org/3/reference/… . ~Q(x=5).exclude
tzot

2

Bu sorunun birçok yanlış cevabına dikkat edin!

Gerard'ın mantığı doğrudur, ancak bir sorgu kümesi yerine bir liste döndürür (bu önemli olmayabilir).

Bir sorgu kümesine ihtiyacınız varsa, Q kullanın:

from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.