2009-09-14 16 views
9

मैं मॉडल, अधिक या कम इस तरह:Django बाएं जॉइन?

class ModelA(models.Model): 
    field = models.CharField(..) 

class ModelB(models.Model): 
    name = models.CharField(.., unique=True) 
    modela = models.ForeignKey(ModelA, blank=True, related_name='modelbs') 

    class Meta: 
     unique_together = ('name','modela') 

मैं एक प्रश्न ऐसा ही कुछ कहते हैं क्या करना चाहते हैं: "जाओ सब ModelA की जहां फ़ील्ड नाम एक्स के नाम के साथ एक ModelB मॉडल है कि करने के लिए बराबर होती है एक्स या कोई मॉडल नाम के साथ सब पर "

अब तक मैं इस है:

यह मैं सभी ModelAs है कि मिल जाएगा कम से कम एक modelB (और वास्तविकता में यह हमेशा सिर्फ एक हो जाएगा) - लेकिन यदि मॉडलए के पास कोई संबंधित मॉडलबी नहीं है, तो यह नहीं होगा परिणाम सेट में नहीं हो। मुझे obj.modelb = none

जैसे कुछ के साथ परिणाम में होना चाहिए, मैं इसे कैसे पूरा कर सकता हूं?

+3

एक तरफ ध्यान दें पर: एसक्यूएल कुछ इस तरह लग रही हवा चाहिए कि वास्तव में मदद चाहते हैं, तो आप ठेठ ब्लॉग/पोस्ट परिदृश्य या जैसे वर्णनात्मक नाम का इस्तेमाल किया मॉडलए/मॉडलबी के बजाय कम से कम Foo/Bar जो गैर-सहज ज्ञान युक्त और पढ़ने/अलग करने के लिए मुश्किल है। –

उत्तर

11

उपयोग क्यू दो शर्तों गठबंधन करने के लिए:

from django.db.models import Q 
qs = ModelA.objects.exclude(field=condition) 
qs = qs.filter(Q(modelbs__name=condition) | Q(modelbs__isnull=True)) 

जिसके परिणामस्वरूप SQL क्वेरी की जांच करने के लिए:

print qs.query.as_sql() 

एक समान क्वेरी पर, यह उत्पन्न करता है एक वाम बाहरी शामिल हों ... जहां (क .val = बी या एआईडी न्यूल है)।

+0

यह मेरे लिए कोई फर्क नहीं पड़ता –

+3

यदि आप यह कहने जा रहे हैं कि "यह काम नहीं कर रहा है", तो मैं निश्चित रूप से आपकी सहायता नहीं कर सकता। क्या आपने एसक्यूएल की भी जांच की? –

+0

हाँ, मैंने किया। खेद है कि मैं और अधिक विशिष्ट नहीं था, मैं कहीं और पाया एक सुझाव की कोशिश में व्यस्त था। वैसे भी, जो कुछ भी आपके पास है, वह हो रहा है, जिसमें शामिल होने की शर्त है, जहां क्लॉज ऑन क्लॉज के विपरीत है, मुझे बिल्कुल यकीन नहीं है कि क्यों यह बाएं शामिल होने की अपेक्षा नहीं करता है। यदि मैं मैन्युअल रूप से उसी क्वेरी को चलाता हूं, जिस स्थिति को चालू किया जाता है, वैसे ही यह काम करता है। –

-3

बाएं जॉइन दो प्रश्नों का एक संघ है। कभी-कभी इसे एक प्रश्न के लिए अनुकूलित किया जाता है। कभी-कभी, यह वास्तव में अंतर्निहित SQL इंजन द्वारा अनुकूलित नहीं किया जाता है और दो अलग-अलग प्रश्नों के रूप में किया जाता है।

ऐसा करें।

for a in ModelA.objects.all(): 
    related = a.model_b.set().all() 
    if related.count() == 0: 
     # These are the A with no B's 
    else: 
     # These are the A with some B's 

एसक्यूएल बाहरी जुड़ने के बारे में "एकल" क्वेरी होने के बारे में बुतलाई न करें।

+5

यह साल पुराना है, लेकिन मैं ध्यान रखना चाहता हूं, भयानक सलाह। यह दृश्यों के पीछे बड़ी संख्या में प्रश्नों को चलाता है, और आसानी से आपकी साइट को क्रॉल में ला सकता है। –

1

ऐसा लगता है कि आप 80% बाधा के खिलाफ आ रहे हैं। सबक्वायरी करने के लिए केवल .extra(select={'has_x_or_none':'(EXISTS (SELECT ...))'}) का उपयोग क्यों न करें? आप सबकुछ को अपनी पसंद के अनुसार लिख सकते हैं और नए फ़ील्ड के खिलाफ फ़िल्टर करने में सक्षम होना चाहिए।

SELECT *, 
    ((EXISTS (SELECT * FROM other WHERE other.id=primary.id AND other.name='X')) 
    OR (NOT EXISTS (SELECT * FROM other WHERE other.id=primary.id))) AS has_x_or_none 
    FROM primary WHERE has_x_or_none=1; 
संबंधित मुद्दे