Bir sorgu kümesindeki boş veya NULL adlar için filtreleme


464

Ben first_name, last_name& aliasben aramak gerekir (opsiyonel). Yani, bana bir takma ad küme tüm adları vermek için bir sorguya ihtiyacım var.

Sadece yapabilseydim:

Name.objects.filter(alias!="")

Peki, yukarıdakine eşdeğer nedir?

Yanıtlar:


842

Bunu yapabilirsin:

Name.objects.exclude(alias__isnull=True)

Boş değerleri ve boş dizeleri hariç tutmanız gerekiyorsa , bunu yapmanın tercih edilen yolu aşağıdaki gibi koşulları birbirine zincirlemektir:

Name.objects.exclude(alias__isnull=True).exclude(alias__exact='')

Bu yöntemleri birlikte zincirlemek temel olarak her koşulu bağımsız olarak kontrol eder: yukarıdaki örnekte, aliasboş veya boş bir dize olan satırları hariç tutarız , böylece Nameboş olmayan, boş olmayan bir aliasalana sahip olan tüm nesneleri elde edersiniz . Oluşturulan SQL şöyle görünecektir:

SELECT * FROM Name WHERE alias IS NOT NULL AND alias != ""

Ayrıca exclude, yalnızca her koşulu karşılayan nesnelerin hariç tutulmasını sağlayan tek bir çağrıya birden fazla argüman iletebilirsiniz :

Name.objects.exclude(some_field=True, other_field=True)

Burada, some_field ve other_field doğru olan satırlar hariç tutulur, böylece her iki alanın doğru olmadığı tüm satırları alırız. Oluşturulan SQL kodu şöyle görünecektir:

SELECT * FROM Name WHERE NOT (some_field = TRUE AND other_field = TRUE)

Alternatif olarak, mantığınız bundan daha karmaşıksa, Django'nun Q nesnelerini kullanabilirsiniz :

from django.db.models import Q
Name.objects.exclude(Q(alias__isnull=True) | Q(alias__exact=''))

Daha fazla bilgi için bu sayfaya ve Django belgelerindeki bu sayfaya bakın.

Bir kenara: SQL örneklerim sadece bir benzetmedir - gerçekte oluşturulan SQL kodu muhtemelen farklı görünecektir. Gerçekte oluşturdukları SQL'e bakarak Django sorgularının nasıl çalıştığını daha iyi anlayacaksınız.


5
Düzenlemenizin yanlış olduğuna inanıyorum: Zincirleme filtresi otomatik olarak bir SQL oluşturmaz OR(sadece bu durumda), bir SQL üretir AND. Referans için bu sayfaya bakın: docs.djangoproject.com/en/dev/topics/db/queries/… Zincirin avantajı, karmaşık sorgu koşullarını karıştırabilmeniz excludeve filtermodellemenizdir. Gerçek bir SQL modellemek istiyorsanız, ORbir Django Q nesnesi kullanmanız gerekir: docs.djangoproject.com/en/dev/topics/db/queries/… Cevabınız geçerli olduğu için ciddi şekilde yanıltıcı olduğundan lütfen düzenlemenizi düzenleyin .
shezi

1
@shezi: Ben daha çok bir benzetme demek istedim - gerçek SQL kodunun ORkoşulları kaynaştırmak için bir kullanacağının garanti edildiği anlamına gelmiyordu . Açıklığa kavuşturmak için cevabımı düzenleyeceğim.
Sasha Chedygov

1
Bu mantığı temsil etmenin farklı yollarının olduğunu unutmayın - örneğin, NOT (A AND B)eşdeğerdir NOT A OR NOT B. Sanırım bu, SQL bilen ancak ORM'lere aşina olmayan yeni Django geliştiricileri için kafa karıştırıcı hale geliyor.
Sasha Chedygov

3
De Morgan yasasını biliyorum ve bu tam olarak benim açımdan: Örneğiniz sadece çalışır çünkü ANDilk sorguyu kullanmak için bir avantaj haline getirdiği ORiçin işe yarar exclude. Genel durumda, zincirlemeyi bir THENyani, yani düşünmek daha doğru olur exclude(A) THEN exclude(B). Yukarıdaki sert dil için üzgünüm. Cevabınız gerçekten iyi, ama yeni geliştiricilerin genel olarak cevabınızı almasından endişe ediyorum.
shezi

2
@shezi: Yeterince adil. Ben Django açısından değil, SQL açısından düşünmek daha iyi olduğunu kabul, sadece sunma açısından zincirleme düşünülmektedir ANDve ORbir SQL arka plandan Django gelen birisi için yararlı olabilir. Django hakkında daha derin bir anlayış için, belgelerin benden daha iyi bir iş çıkardığını düşünüyorum.
Sasha Chedygov

50
Name.objects.filter(alias__gt='',alias__isnull=False)

2
Emin değilim, ama alias__isnull=Falsedurumun fazla olduğunu düşünüyorum . Eğer alan Nullkesinlikle ise ilk fıkra tarafından hariç tutulur mu?
Bobble

Daha önceki yorumum / sorum dışında, buradaki mantığın takip edilmesinin diğer cevaplardan daha kolay olduğunu düşünüyorum.
Bobble

@Bobble veritabanı uygulamasına bağlı olacak - sipariş
wpercy

alias__gtBoş dizeleri JSON gibi hariç tutmak istediğim JSON türü sütunlar için çalışan tek şeydi {'something:''}. Yani çalışma sözdizimi:jsoncolumnname__something__gt=''
bartgras

38

İlk olarak, Django belgeleri CharField veya TextField gibi dize tabanlı alanlar için NULL değerlerinin kullanılmamasını önemle tavsiye eder. Açıklama için belgeleri okuyun:

https://docs.djangoproject.com/en/dev/ref/models/fields/#null

Çözüm: Bence QuerySets'te yöntemleri birbirine bağlayabilirsiniz. Bunu dene:

Name.objects.exclude(alias__isnull=True).exclude(alias="")

Bu size aradığınız seti vermelidir.


5

Django 1.8'den,

from django.db.models.functions import Length

Name.objects.annotate(alias_length=Length('alias')).filter(alias_length__gt=0)

5
Buna "Eğer bir şey gibi görünüyor olabilir yapmak", değil bir şey olmalıdır yapmak. İki basit kontrol üzerinde sorgu karmaşıklığını önemli ölçüde açar.
Oli

3

Kullanırken sık yapılan hataları önlemek için şunu excludeunutmayın:

Sen olabilir değil eklemek birden içine koşulları bir dışlama () gibi bloğun filter. Birden çok koşulu hariç tutmak için birden çok exclude () kullanmanız gerekir

Misal

Yanlış :

User.objects.filter (email='example@example.com '). Hariç tut (profile__nick_name =' ', profile__avt =' ')

Doğru :

User.objects.filter (email='example@example.com '). (= Profile__nick_name hariç'. ') Hariç (profile__avt =' ')


0

Bunu basitçe yapabilirsiniz:

Name.objects.exclude(alias="").exclude(alias=None)

Gerçekten bu kadar basit. filter, excludebelirttiği şey dışında her şeyi eşleştirmek için kullanılır . Bu SQL olarak değerlendirir NOT alias='' AND alias IS NOT NULL.


Bu yanlış. Soru, boş ( alias="") ve NULL ( alias=None) takma adlarını sorgudan hariç tutmayı amaçlamaktadır . Sizinki ile örnekleri içerir Name(alias=None).
damon

@damon - Başlığa .filter(alias!="")değil, eşdeğer olana cevap veriyordum . Cevabımı düzenledim. Ancak, karakter alanları NULL değerlere izin vermemeli ve değer içermeyen boş dizeyi kullanmalıdır (kurallara göre).
Tim Tisdall

-1

bu, bunu yapmanın başka bir basit yoludur.

Name.objects.exclude(alias=None)

Noneile aynı şey değildir "".
Tim Tisdall
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.