2017-12-14 121 views
5

मेरे पास एक ऐसी प्रणाली है जहां एक मॉडल के साथ कई संबंध हैं (कहें 1 ए -> कई बी) और कई मॉडल के दूसरे मॉडल के साथ एक से एक रिश्ते है (1 बी -> 1 सी कहें)। इसलिए तरह तैयार:Django एक-से-एक रिश्ते के साथ एक से कई लोगों को चेन करने के लिए क्वेरीसेट निर्धारित नहीं कर सकता

/--- b1 --- c1 
/
a ---- b2 --- c2 
\ 
    \--- b3 --- c3 

मैं एक विधि बनाने के लिए है कि सभी c की कि a के अनुरूप जमा करता है में निर्धारित कर रहा हूँ।

एक ही संरचना के साथ एक मॉडल सिस्टम को देखते हुए, सबसे अच्छा मैं इस विधि में दिखाया जा सकता है: Person.find_important_treats()

क्या कोई बेहतर तरीका है जिसमें डेटाबेस में इतनी सारी कॉल शामिल नहीं हैं? और

def find_important_treats(self): 
    return Treat.objects.filter(id__in=person.pets.values_list('treat_id')) 

यह Treat रों है कि पालतू जानवरों की ids के सभी प्राप्त तो उन्हें रिटर्न:

from django.db import models 

class Person(models.Model): 
    """ The 'a' from my above example """ 

    def find_important_treats(self): 
     return (pet.treat for pet in self.pets) 

class Pet(models.Model): 
    """ The 'b' from my above example """ 

    owner = models.ForeignKey(
     to=Person, 
     related_name='pets' 
    ) 

    favourite_treat = models.ForeignKey(
     to=Treat, 
    ) 

class Treat(models.Model): 
    """ The 'c' from my above example """ 
    pass 
+1

इन पंक्तियों के साथ हो सकता है आप पाएंगे जवाब 'Treat.objects.filter (pet__owner__pk = personId)' के लिए है। – aquaman

+1

क्या आप अधिक विशिष्ट हो सकते हैं, क्या आप पूरे इलाज की वस्तुओं में अंतर रखते हैं या इलाज आईडी को जोड़ते हैं? इससे बड़ा फर्क पड़ता है! – DhiaTN

+0

@DiaTNN, मुझे पूरा इलाज चाहिए (लालची मुझे), क्योंकि इसमें जानकारी है जो मैं अपने टेम्पलेट में प्रस्तुत करना चाहता हूं। – Splatmistro

उत्तर

4

मैं आपके उपयोग के मामले के आधार पर दो लगभग समान समाधान का सुझाव:

class Person(models.Model): 
     """ The 'a' from my above example """ 

     @property 
     def iter_important_treats(self): 
      return iter(self.pets.values_list('treat_id', flat=True)) # caching will not affect the query behviour 

    person = Person.objects.get(id=person_id) 
    treats = Treat.objects.filter(id__in=person.iter_importent_treats) 
:

  • का उपयोग कैशिंग
class Person(models.Model): 
     """ The 'a' from my above example """ 

     @property 
     def iter_important_treats(self): 
      return (pet.treat_id for pet in self.pets.all()) # will use the cached objects if they exist 

    person = Person.objects.get(id=person_id).select_related('pets') # to cache the pets list within the person object avoiding future additional queries 
    treats = Treat.objects.filter(id__in=person.iter_importent_treats) 
  • कैशिंग का उपयोग करते हुए बिना

    एनबी:

    1. हम, treat_id बजाय treat__id का उपयोग अतिरिक्त से बचने के लिए प्रश्नों में शामिल होने क्योंकि Django पालतू वस्तु स्तर पर पहले से ही treat_id की बचत होती है, लेकिन यदि आप treat__id का उपयोग तो आप एक में शामिल होने के लिए मजबूर क्वेरी।
    2. आईडी की पुनरावर्तक के लिए संपत्ति सीमित बस उलटने और रख-रखाव खातिर
2

निम्नलिखित आप के बाद क्या कर रहे हैं क्या करना चाहिए।

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