2016-02-08 6 views
5

मैं बहुत की तरह एक मॉडल है में रहने वाले बच्चों को इकट्ठा ....रिकर्सिवली पायथन/Django

class Person(models.Model): 
    name = models.CharField(max_length=55,null=False, blank=False) 
    parent = models.ForeignKey('Person.Person', null=False, blank=False) 

मैं एक पुनरावर्ती समारोह है कि अंततः एक पूरे व्यक्तियों वंश-वृक्ष की एक शब्दकोश वापस आ जाएगी बनाना चाहते हैं ....

इसलिए उदाहरण के लिए

...

first_person = Person.objects.filter(name='FirstPerson') 
family_tree = GetChildren(first_person) 

कहाँ GetChildren मेरी पुनरावर्ती क्रिया कि लगातार GetChildren फोन करेंगे, जब तक वहाँ कोई और अधिक बच्चे हैं ... यह तो एक dictio लौटना चाहिए आम कि इतने की तरह इन बच्चों के सभी रखती है ...

{ 
    'name': 'FirstPerson', 
    'children': [ 
     { 
      'name': 'FirstPersonChild1' 
      'children': [ ... ] 
     }, 
     { 
      'name': 'FirstPersonChild2' 
      'children': [ ... ] 
     } 
    ] 
} 

मैं प्रत्यावर्तन के साथ अच्छा नहीं किया गया, किसी ने मन समझा जाएगा कि कैसे मैं इस को पूरा करने के बारे में जाना होगा ...

+1

@Prune आपका नाम वास्तव में आप सूट। – Ricky

उत्तर

2

इस कार्यान्वयन काम करना चाहिए

def get_family_tree(person): 
    """ return a family tree for a Person object """ 

    children = person.children.all() 

    if not children: 
     # this person has no children, recursion ends here 
     return {'name': person.name, 'children': []} 

    # this person has children, get every child's family tree 
    return { 
     'name': person.name, 
     'children': [get_family_tree(child) for child in children], 
    } 

ध्यान दें कि यह के रूप में ले जाएगा:

first_person = Person.objects.filter(name='FirstPerson') 
family_tree = first_person.getChildren() 

getChildren कुछ इस तरह दिखेगा कहाँ कई डेटाबेस कॉल हैं क्योंकि व्यक्ति हैं। यदि आप प्रदर्शन समस्याओं में भाग लेते हैं तो आप सभी डेटा को मेमोरी में लाने की कोशिश कर सकते हैं। अर्थात जहां प्रत्यावर्तन खत्म हो जाएगा -

में सोच रही थी Recursion बारे

एक प्रत्यावर्तन के बारे में सोचने के लिए रास्ता आधार मामले के साथ शुरू करने के लिए है। आपके मामले में, हम जानते हैं कि कैसे वंश-वृक्ष यदि एक व्यक्ति से कोई संतान नहीं है जैसा दिखता है:

{ 
    'name': 'FirstPerson', 
    'children': [], 
} 

के बाद आप आधार मामले (रों) है, समस्या है जहाँ आप एक बार प्रत्यावर्तन प्रदर्शन करने के लिए है के बारे में सोचते हैं।

आपके मामले में, यह बच्चों के साथ माता-पिता होगा, लेकिन कोई भव्य बच्चा नहीं होगा। हम जानते हैं कि प्रत्येक बच्चे के परिवार के पेड़ को कैसे देखना चाहिए - यह सिर्फ आधार मामला है! इससे हमें समाधान मिल जाता है जहां हम माता-पिता का नाम वापस लेते हैं, और प्रत्येक बच्चे के परिवार के पेड़ की एक सूची। की तरह कुछ करने के लिए अग्रणी:

{ 
    'name': FirstPerson, 
    'children': [<each element is a child's family tree>] 
} 

संपादित

Django स्वचालित रूप से एक ForeignKey के लिए रिवर्स संबंधों उत्पन्न करता है।

class Person(models.Model): 
    .... 
    parent = models.ForeignKey('self', related_name='children', blank=True, null=True) 

p = Person() 
p.children.all() # automatically fetch all Person objects where parent=p 

देखें https://docs.djangoproject.com/en/1.9/ref/models/fields/#foreignkey

+0

यह इसके बारे में सोचने का एक अच्छा तरीका है (मूल मामले और ऐसे)। मैं इसे आज़मा दूंगा और आपको बता दूंगा कि यह कैसे निकलता है। मुझे बस थोड़ा सा tweek करने की जरूरत है, क्योंकि मॉडल अपने बच्चों को स्टोर नहीं करता है ... यह अपने माता-पिता को संग्रहीत करता है। – Ricky

+1

आप सीधे एक व्यक्ति मॉडल से बच्चों तक पहुंच सकते हैं, Django स्वचालित रूप से आपके लिए रिवर्स रिलेशनशिप उत्पन्न करता है। यदि आपने पैरेंट फ़ील्ड के लिए 'related_name' निर्दिष्ट नहीं किया है, तो ऑटो जनरेट किया गया नाम' person_set' होगा। आप 'person.person_set.all()' –

+0

पर बच्चों तक पहुंचेंगे ओह, यह एक निफ्टी छोटी चाल है! धन्यवाद! यह 100% काम किया। – Ricky

1

आप ऐसा कर सकते हैं मॉडल पर एक कस्टम विधि लिखना। जिस तरह से आप इसे कहते कुछ इस तरह दिखेगा:

def getChildren(self): 
    children = Person.objects.filter(parent=self) 
    # return children 
    # OR just format the data so it's returned in the format you like 
    # or you can return them as Person objects and have another method 
    # to transform each object in the format you like (e.g Person.asJSON()) 
+0

यह केवल एक स्तर के परिणाम उत्पन्न करेगा। मैं पेड़ को जितना संभव हो उतना नीचे जाना चाहता हूं (जब तक पेड़ में किसी व्यक्ति के बच्चे न हों)। तो फर्स्टपर्सन में एक बच्चा हो सकता है, लेकिन उस बच्चे के पास 4 बच्चे हो सकते हैं, प्रत्येक अपने बच्चों के साथ। – Ricky

0

यह काम करता है महान या इस उद्देश्य के रूप में आप पैकेज django-mptt प्रयास करना चाहिए:

आप ForeignKey रूप TreeForeignKey() उपयोग कर सकते हैं।

फिर आप वस्तुओं मिलता है (या डॉक्स मैं बजाय बच्चों माता-पिता/पूर्वजों प्राप्त करने के लिए प्रदान की है इस पर गौर) के मॉडल के लिए इस विधि जोड़ सकते हैं:

def get_category_and_parents(self): 
    """ Recursively retrieves parent categories (including self) using MPTT """ 
    full_category = self.category.get_ancestors(include_self=True) 
    return full_category 

Github:

https://github.com/django-mptt/django-mptt

डॉक्स:

http://django-mptt.github.io/django-mptt/mptt.models.html#mptt.models.MPTTModel.get_children

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