2011-03-02 15 views
8

मैं निम्नलिखित मॉडल के साथ एक Django आवेदन किया है: एक एक सरल कुछ क्षेत्रों के साथ मॉडल से विस्तार वस्तु हैलाई जा रही है Django में विरासत में मिला मॉडल वस्तुओं

वस्तु, और मान लें, एक विशेष रूप से एक एक चार क्षेत्र है "NAME" और "ORDER" नामक एक इंटीजर फ़ील्ड कहा जाता है। एक, सार है जिसका अर्थ है कोई डेटाबेस में एक वस्तुओं, लेकिन इसके बजाय ...

वस्तुओं बी और देखते हैं सीएक की विशेषज्ञताओं हैं, अर्थात अपने एक और से विरासत वे कुछ अन्य क्षेत्रों को जोड़ते हैं।

अब मैं सभी वस्तुओं जिसका क्षेत्र नाम की आवश्यकता अक्षर से शुरू लगता "Z", आदेश क्षेत्र द्वारा आदेश दिया है, लेकिन मैं सभी बी और सी विशिष्ट क्षेत्रों भी चाहते हैं उन वस्तुओं के लिए। अब मैं 2 दृष्टिकोण देखें:

क) बी और सी वस्तुओं के लिए प्रश्नों को व्यक्तिगत रूप से करते हैं और मैन्युअल रूप से दो सूचियों लाने, उन्हें मर्ज, आदेश और उस के साथ काम करते हैं।

ख) क्वेरी "Z""आदेश" द्वारा और बी और सी वस्तुओं परिणाम क्वेरी के साथ आदेश दिया सभी शेष डेटा लाने के लिए के साथ शुरू नाम के लिए एक वस्तुओं।

दोनों दृष्टिकोण बहुत अक्षम हैं, पहले मुझे उन्हें स्वयं ऑर्डर करना होगा, दूसरे में मुझे डेटाबेस को कई बार पूछना होगा।

वहाँ एक जादुई तरह से मैं सभी बी और सी वस्तुओं, एक ही विधि में आदेश दिया लाने के लिए याद कर रहा हूँ है? या दोनों का उल्लेख करने के लिए कम से कम एक और अधिक प्रभावी तरीका है?

अग्रिम में धन्यवाद!

ब्रूनो

+1

Django मॉडल विरासत में आपका स्वागत है। यहां रहने का आनंद। –

उत्तर

5

यदि A कंक्रीट हो सकता है, तो आप इसे select_related का उपयोग करके एक ही प्रश्न में कर सकते हैं।

from django.db import connection 
q = A.objects.filter(NAME__istartswith='z').order_by('ORDER').select_related('b', 'c') 
for obj in q: 
    obj = obj.b or obj.c or obj 
    print repr(obj), obj.__dict__ # (to prove the subclass-specific attributes exist) 
print "query count:", len(connection.queries) 
+0

चालाक। भयानक, लेकिन चालाक। हालांकि ए एक सार है जब काम नहीं करेगा? – Wogan

+0

केवल सही, कंक्रीट बहु-टेबल विरासत। – DrMeers

+0

आह, मैंने अपने प्रारंभिक पढ़ने पर वाक्यांश "ए इज सार" छोड़ने में कामयाब रहे ... – DrMeers

0

अपने "बी" पद्धति का उपयोग करके पता कर रहा है, तो आप के लिए अलग से अपने बी और सी मॉडल से पूछे बिना सभी शेष डेटा "में लाने के लिए" की अनुमति देगा। आप "डॉट लोअरकेस मॉडल नाम" संबंध का उपयोग कर सकते हैं।

http://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance

for object in A.objects.filter(NAME__istartswith='z').order_by('ORDER'): 
    if object.b: 
     // do something 
     pass 
    elif object.c: 
     // do something 
     pass 

आप DoesNotExist अपवादों को छोड़कर कोशिश करते हैं और करना पड़ सकता है। मैं अपने django के साथ थोड़ा जंगली हूँ। शुभ लाभ।

+0

हां, आपको 'DoNotExist' को पकड़ने की आवश्यकता होगी, और संबंधित ऑब्जेक्ट (सफल या नहीं) तक पहुंचने के प्रत्येक प्रयास से आपको अतिरिक्त क्वेरी मिल जाएगी - बहुत अक्षम। – DrMeers

0

इतने लंबे समय के रूप में आप बी और सी पर दोनों प्रश्नों के आदेश, यह एक महंगी रिसॉर्ट करने के लिए बिना उन्हें एक करना काफी आसान है:

# first define a couple of helper functions 

def next_or(iterable, other): 
    try: 
     return iterable.next(), None 
    except StopIteration: 
     return None, other 

def merge(x,y,func=lambda a,b: a<=b): 
    ''' merges a pair of sorted iterables ''' 
    xs = iter(x) 
    ys = iter(y) 
    a,r = next_or(xs,ys) 
    b,r = next_or(ys,xs) 
    while r is None: 
     if func(a,b): 
      yield a 
      a,r = next_or(xs,ys) 
     else: 
      yield b 
      b,r = next_or(ys,xs) 
    else: 
     if a is not None: 
      yield a 
     else: 
      yield b 
    for o in r: 
     yield o 

# now get your objects & then merge them 

b_qs = B.objects.filter(NAME__startswith='Z').order_by('ORDER') 
c_qs = C.objects.filter(NAME__startswith='Z').order_by('ORDER') 

for obj in merge(b_qs,c_qs,lambda a,b: a.ORDER <= b.ORDER): 
    print repr(obj), obj.__dict__ 

इस तकनीक का लाभ यह के साथ काम करता है एक सार आधार वर्ग।

संबंधित मुद्दे