Django sorguda / değil


100

Django'da 'olmayan' tarzı bir sorguyu nasıl yazacağımı bulmaya çalışıyorum. Örneğin, düşündüğüm sorgu yapısı şöyle görünecektir.

select table1.* 
from table1
where table1.id not in 
(
  select table2.key_to_table1
  from table2 
  where table2.id = some_parm 
)

Django sözdizimi, tablo1 ve tablo2 olarak adlandırılan modelleri varsayarsak neye benzerdi?

Yanıtlar:


164
table1.objects.exclude(id__in=
    table2.objects.filter(your_condition).values_list('id', flat=True))

Hariç tutma işlevi, Notistediğiniz yerdeki operatör gibi çalışır . Özellik flat = True, table2sorguya value_listbir düzey liste olarak dönmesini söyler . Yani ... sonunda IDs, kullanıcısı tarafından koşulu tanımlayacağınız table1, dışlama fonksiyonu tarafından reddedilecek olan tablo2'den bir liste alıyorsunuz .


3
Ayrıca liste yapıcı [tablo2 ...] -> liste (tablo2 ...) benim için çalıştı.
RickyA

3
düzeltme: table1.objects.exclude (id__in = table2.objects.filter (your_condition) .values_list ('id', flat = True))
Richard

1
Bu çözümü kullanmaya çalışıyordu ve bir sorunla karşılaştı, bu yüzden başkasının başına gelirse ... Objs=Tbl1.objects.filter(...); IDs=Objs.values_list('id', flat=True); Objs.delete(); Tbl2.objects.filter(id__in=IDs')Kimlikler aslında bir QuerySet nesnesi olduğu için bu işe yaramadı. Kaynak olduğu satırları sildiğimde artık diğer sorgularla çalışmıyordu. Çözüm Tbl2.objects.filter(id__in=list(IDs))- listeye çevirin
Dakusan

1
Bağlama bağlı olarak, filtre "sayı (xx) == yy" gibi ise, kullanımı 100 kattan daha hızlıdır annotate()(timeit bana 1.0497902309998608'e karşı 0.00514069400014705 verdi)
Olivier Pons

10

bu modellerle:

class table1(models.Model):
    field1 = models.CharField(max_length=10)      # a dummy field

class table2(models.Model):
    key_to_table1 = models.ForeignKey(table1)

kullanarak istediğini almalısın:

table1.objects.exclude(table2=some_param)

1
Bu hala potansiyel olarak çok sayıda kaydı gereksiz yere veritabanından çekmenize neden olur.
Jay Taylor

5
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])

1

Django sorguları için özel bir arama yazabilirsiniz:

Gönderen belgelerinde : "Basit bir özel arama ile edelim başından Biz özel bir arama yazacak NE tersini çalışır kesin . Author.objects.filter (name__ne = 'Jack') SQL çevirmek olacaktır: "author"."name" <> 'Jack'"

from django.db.models import 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

-16
[o1 for o1 in table1.objects.all() if o1.id not in [o2.id for o2 in table2.objects.filter(id=some_parm)]]

Ya da daha iyisi

not_in_ids = [obj.id for obj in table2.objects.filter(id=some_parm)]
selected_objects = [obj for obj in table1.objects.iterator() if obj.id not in not_in_ids]

12
Bir tablodaki her satırın üzerinde yineleme. gg
Rebs
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.