2011-02-01 9 views
5

मैं (डेटा फ़ील्ड छोड़े गए) इस तरह की एक Django डाटा मॉडल है: तो यह Transition.objects.filter(...) पर क्वेरी करने के लिए सबसे आसान है,Django नेस्टेड क्वेरीसमूहों

class Atom(Model): 
    pass 

class State(Model): 
    atom = ForeignKey(Atom) 

class Transition(Model): 
    atom = ForeignKey(Atom) 
    upstate = ForeignKey(State,related_name='uptrans') 
    lostate = ForeignKey(State,related_name='lotrans') 

जब मैं क्वेरी, खेतों या तो मॉडल में हो सकता है प्रतिबंधित किया जा करने के लिए चूंकि अन्य मॉडलों के सभी क्षेत्रों को विदेशी कुंजी के माध्यम से पहुंचा जा सकता है। आइए परिणामी QuerySet t पर कॉल करें।

अब जो मैं चाहता हूं वह एटम मॉडल का एक क्वेरीसेट a है जो t से मेल खाता है, जो a = t.values('atom').distinct() जैसा किया जा सकता है। अब तक सब ठीक है।

हालांकि, मैं भी a में प्रविष्टियों में से प्रत्येक के लिए चाहते हैं upstate दोनों में से किसी एक के माध्यम से एक विशेषता/क्षेत्र है कि इस एटम, अभी भी मूल चयन t पर मापदंड को दर्शाती है की स्टेट्स क्वेरीसमूह रखती है, के लिए या lostate विदेशीकेज़।

मैं अब तक t से अधिक पाशन, डुप्लिकेट बाहर फेंक, और फिर इस सूची के साथ अमेरिका की क्वेरी के लिए values('upstate_id') और values('lostate_id') एक अजगर set() को जोड़कर स्टेट्स पर मेरे क्वेरीसमूह बनाया है। लेकिन फिर मैं परमाणुओं के भीतर राज्यों की घोंसला वाली संरचना को प्राप्त नहीं कर सकता।

अनगिनत QuerySet एस के साथ यदि संभव हो तो यह करने के तरीके पर कोई सुझाव है, क्योंकि मैं उन्हें टेम्पलेट में नहीं बल्कि एक जनरेटर (yield कथन) पास करता हूं, जो बड़ी मात्रा में डेटा स्ट्रीम करने का एक अच्छा तरीका है।

उत्तर

2

मुझे लगता है कि निम्न कार्य जो मैंने ऊपर वर्णित किया है, लेकिन मुझे यकीन नहीं है कि परमाणु द्वारा मूल क्वेरीसेट के आगे फ़िल्टरिंग के साथ लूप सही दृष्टिकोण है या नहीं।

someAtoms = getAtomsWithStates(Transition.objects.filter(...)) 
for atom in someAtoms: 
    for state in atom.States: 
     print state.field 

एक बार फिर से लेकिन,, वहाँ इस के लिए एक स्मार्ट समाधान हो सकता है और मैं निश्चित रूप से दिलचस्पी होगी:

def getAtomsWithStates(t): 
    atom_ids = set(t.values_list('atom_id',flat=True)) 
    atoms = Atoms.objects.filter(pk__in=atom_ids) 
    for atom in atoms: 
     upstate_ids = t.filter(atom=atom).values_list('upstate_id',flat=True) 
     lostate_ids = t.filter(atom=atom).values_list('lostate_id',flat=True) 
     all_ids = set(upstate_ids + lostate_ids) 

     # attach the new QuerySet to the entry in the outer one: 
     atom.States = State.objects.filter(pk__in=all_ids) 

    return atoms 

अब मैं नेस्टेड पाश है कि मैं इस तरह की जरूरत है क्या कर सकते हैं।

0

यह बहुत अच्छा है कि आपको set एस की समझ है। हालांकि, एसक्यूएल के In का उपयोग करके आपके डेटा को डुप्लिकेट नहीं किया जाएगा। चलो एक पल के लिए मानते हैं। अगर मैं कहता हूं, "मुझे इस पर एक परमाणु दें: (1, 2, 3, 3, 3, 4)," डेटाबेस परमाणु 1, 2, 3, और 4 लौटाएगा। सरलीकरण के लिए, मैं नहीं पाइथन को set अंकगणित करने के लिए कहें क्योंकि डेटाबेस इसे ठीक से संभालने में सक्षम होना चाहिए। set का उपयोग करने के कई बार हैं, लेकिन आपका परिदृश्य उनमें से एक जैसा प्रतीत नहीं होता है।

आप के लिए एक विकल्प:

states = State.objects.filter(
    Q(pk__in=t.values_list('upstate', flat=True)) | 
    Q(pk__in=t.values_list('lostate', flat=True) 
) 

फिर भी, यह अपने मॉडल कुछ परिवर्तन इस्तेमाल कर सकते हैं की तरह लगता है, लेकिन मैं पूरी तरह से समझ में नहीं आता कि आप क्या हासिल करने की कोशिश कर रहे हैं। ध्यान दें कि मेरे विकल्प में, मैं परमाणुओं के साथ कुछ नहीं करता हूं। मैं Q ऑब्जेक्ट का उपयोग करने के लिए एक ऑपरेशन करने में सक्षम होने के लिए उपयोग करता हूं, लेकिन आप राज्य मॉडल में ध्वज जोड़ने में सक्षम हो सकते हैं यह इंगित करने के लिए कि यह उच्च या निम्न है या नहीं। या आप तालिका के माध्यम से एक एम 2 एम संबंध का उपयोग कर सकते हैं। और आपका संक्रमण और आपका राज्य दोनों परमाणु से क्यों जुड़ा होगा?तुम बस Transition से atom को खत्म करने और इसलिए तरह State से atom मिल सकता है:

atoms = Atom.objects.filter(
    pk__in=State.objects.filter(
     Q(pk__in=t.values_list('upstate', flat=True)) | 
     Q(pk__in=t.values_list('lostate', flat=True) 
    ).values_list('atom', flat=True) 
) 
संबंधित मुद्दे