2011-03-25 18 views
39

Aşağıdaki Django modeli vardır: o (doğrudan SQL yazmadan) mümkünseDjango sorgu kümesi ters yabancı anahtar

class Make: 
    name = models.CharField(max_length=200) 

class MakeContent: 
    make = models.ForeignKey(Make) 
    published = models.BooleanField() 

ben bilmek istiyorum bana bütün Make içeren bir Sorgu Kümesi oluşturmak için s ve her birinin MakeContent s ile ilgili olduğu published = True.

+0

Sorunuz hakkında daha spesifik olabilir misiniz? – pyeleven

cevap

9

Django, ters yabancı anahtar aramaları için select_related() yöntemini desteklemez, böylece Python'dan ayrılmadan yapabileceğiniz en iyi iki veritabanı sorgusudur. Birincisi yayınlanan = True olan MakeContents içeren tüm Maksatları ele almak, ikincisi yayınlanan = True olan tüm MakeContents'ı ele almaktır. Ardından, verileri nasıl aradığınız ve nasıl istediğinizi ayarlamanız gerekiyor. İşte bu nasıl yapılacağı hakkında iyi bir makale:

http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/

+18

Bu soruya şimdi yanıt vermem gerektiğini düşünmüyorum ... –

+2

bahsettiğiniz iki soruyu akıcı hale getirmek için prefetch_related() yöntemine bakın. Yanılmıyorsa –

42

Evet, sana

make = Make.objects.get(pk=1) 
make.make_content_set.filter(published=True) 

ya da belki

make_ids = MakeContent.objects.filter(published=True).values_list('make_id', flat=True) 
makes = Make.objects.filter(id__in=make_ids) 
+3

'.values ​​'' .values_list' ile değiştirilmelidir. – exfizik

+1

İlk kod snippet'iniz çalışmıyor. Tüm MakeContents'ları * bir * make için alır, burada MakeContents for All Makes gereklidir. _set tek bir nesne için çalışır, ancak bir queryset için değil. – knite

+0

'flat = True' ekleme noktası nedir? Kimlikler zaten tanım gereği benzersiz olacak ve benzersiz olduklarını bir kez daha ek bir hesaplama gerektirebilir. – pintoch

9

beni için kodları içine Spike'ın ifadeli cevabı tercüme edelim istediğini düşünüyorum gelecek görüntüleyenler. Her 'yap' katına sıfır olabilir unutmayınız 'MakeContent'

asker EN AZ BİR 'MakeContent' kimin = Doğru yayınlanan daha sonra Jason Christa'nın 2 pasajı soru cevaplar ile 'Yap' sorgulamak için demekse .

pasajı

makes = Make.objects.select_related().filter(makecontent__published=True).distinct() 

eşdeğerdir Ama asker sorgulamak demektir eğer TÜM 'MakeContent' yayınlanmış = Doğru, o zaman, yukarıdaki 'yapar' Aşağıdaki

import operator 
make_ids = [m.id for m in makes if 
    reduce(operator.and_, [c.published for c in m.makecontent_set.all()]) 
] 
makes_query = Make.objects.filter(id__in=make_ids) 
ile 'Yap'

, istenen sorguyu içerir.

4

Bunun çok eski bir soru olduğunu biliyorum, ama ben cevap veriyorum. Sanırım cevabım başkalarına yardım edebilir. Modeli biraz değiştirdim. Django 1.8 kullandım.

class Make(models.Model): 
    name = models.CharField(max_length=200) 

class MakeContent(models.Model): 
     make = models.ForeignKey(Make, related_name='makecontent') 
     published = models.BooleanField() 

Aşağıdaki queryset'i kullandım.

Make.objects.filter(makecontent__published=True) 

Yardım edin.