डीआरएफ एपीआई के साथ मेरा डीजेगो-संचालित ऐप ठीक काम कर रहा है, लेकिन मैंने प्रदर्शन समस्याओं में भागना शुरू कर दिया है क्योंकि डेटाबेस वास्तविक डेटा के साथ पॉप्युलेट हो जाता है। मैंने Django डीबग टूलबार के साथ कुछ प्रोफाइलिंग की है और पाया है कि मेरे कई अंतराल बिंदु अपने डेटा लौटने के दौरान सैकड़ों प्रश्नों को जारी करते हैं।Django REST Framework: नेस्टेड धारावाहिकों के लिए प्रीफेचिंग सेट करना
मुझे उम्मीद थी, क्योंकि मैंने पहले डेटाबेस क्वेरी के संबंध में कुछ भी अनुकूलित नहीं किया था। अब जब मैं प्रीफेचिंग स्थापित कर रहा हूं, हालांकि, मुझे ठीक से प्रीफेच किए गए सीरिएलाइज़र डेटा का उपयोग करके परेशानी हो रही है जब उस धारावाहिक को एक अलग धारावाहिक में घोंसला दिया जाता है। मैं prefetch के विभिन्न तरीकों के बारे में सोचने के लिए एक गाइड के रूप में इस awesome post का उपयोग कर रहा हूं।
वर्तमान में, सीरिएलाइज़र ठीक से प्रीफ़ेच करता है जब मैं /api/readinggroups/
एंडपॉइंट पर हिट करता हूं। मेरा मुद्दा /api/userbookstats/
एंडपॉइंट है, जो सभी UserBookStats
ऑब्जेक्ट्स देता है। संबंधित धारावाहिक, UserBookStatsSerializer
, नेस्टेड ReadingGroupSerializer
है।
मॉडल, serializers, और viewsets इस प्रकार हैं:
models.py
class ReadingGroup(models.model):
owner = models.ForeignKeyField(settings.AUTH_USER_MODEL)
users = models.ManyToManyField(settings.AUTH_USER_MODEL)
book_type = models.ForeignKeyField(BookType)
....
<other group related fields>
def __str__(self):
return '%s group: %s' % (self.name, self.book_type)
class UserBookStats(models.Model):
reading_group = models.ForeignKey(ReadingGroup)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
alias = models.CharField()
total_books_read = models.IntegerField(default=0)
num_books_owned = models.IntegerField(default=0)
fastest_read_time = models.IntegerField(default=0)
average_read_time = models.IntegerField(default=0)
serializers.py
class ReadingGroupSerializer(serializers.ModelSerializer):
users = UserSerializer(many = True,read_only=True)
owner = UserSerializer(read_only=True)
class Meta:
model = ReadingGroup
fields = ('url', 'id','owner', 'users')
@staticmethod
def setup_eager_loading(queryset):
#select_related for 'to-one' relationships
queryset = queryset.select_related('owner')
#prefetch_related for 'to-many' relationships
queryset = queryset.prefetch_related('users')
return queryset
class UserBookStatsSerializer(serializers.HyperlinkedModelSerializer):
reading_group = ReadingGroupSerializer()
user = UserSerializer()
awards = AwardSerializer(source='award_set', many=True)
class Meta:
model = UserBookStats
fields = ('url', 'id', 'alias', 'total_books_read', 'num_books_owned',
'average_read_time', 'fastest_read_time', 'awards')
@staticmethod
def setup_eager_loading(queryset):
#select_related for 'to-one' relationships
queryset = queryset.select_related('user')
#prefetch_related for 'to-many' relationships
queryset = queryset.prefetch_related('awards_set')
#setup prefetching for nested serializers
groups = Prefetch('reading_group', queryset ReadingGroup.objects.prefetch_related('userbookstats_set'))
queryset = queryset.prefetch_related(groups)
return queryset
views.py
class ReadingGroupViewset(views.ModelViewset):
def get_queryset(self):
qs = ReadingGroup.objects.all()
qs = self.get_serializer_class().setup_eager_loading(qs)
return qs
class UserBookStatsViewset(views.ModelViewset):
def get_queryset(self):
qs = UserBookStats.objects.all()
qs = self.get_serializer_class().setup_eager_loading(qs)
return qs
मैं ReadingGroup
endpoint के लिए प्रीफेचिंग अनुकूलन किया है (मैं वास्तव में है कि अंत बिंदु here के लिए डुप्लिकेट प्रश्नों को नष्ट करने के बारे में पोस्ट), और अब मैं UserBookStats
समाप्ति बिंदु पर काम कर रहा हूँ।
मुद्दा मैं आ रही है कि, के साथ मेरे वर्तमान setup_eager_loading
UserBookStatsSerializer
में, यह प्रीफेचिंग ReadingGroupSerializer
में उत्सुक लोड हो रहा है विधि द्वारा स्थापित उपयोग करने के लिए प्रकट नहीं होता है। मैं अभी भी Prefetch
ऑब्जेक्ट के सिंटैक्स पर थोड़ा आलसी हूं - मैं उस दृष्टिकोण को आजमाने के लिए this उत्कृष्ट उत्तर से प्रेरित था।
जाहिर UserBookStatsViewset
की get_queryset
विधि ReadingGroup
वस्तुओं के लिए setup_eager_loading
फोन नहीं है, लेकिन मैं वहाँ एक ही प्रीफेचिंग पूरा करने के लिए एक रास्ता है यकीन है।
क्या आप सुरुचिपूर्ण समाधान या किसी समाधान के बारे में पूछ रहे हैं? 'queryset = queryset.prefetch_related ('read_group', 'reading_group__users', 'reading_group__owner') 'ठीक काम करना चाहिए। – serg
कोई भी समाधान बहुत अच्छा होगा - और वाह, यह कमाल है। यह पूरी तरह से काम करता है, इसलिए यदि आप इसे उत्तर के रूप में सबमिट करते हैं, तो मैं स्वीकार करूंगा। यह 'प्रीफेच' ऑब्जेक्ट को प्रतिस्थापित करता है, जो कि मैं एक सुरुचिपूर्ण समाधान के लिए उपयोग करने की उम्मीद कर रहा था जो कि डीक्यूपल प्रीफेचिंग की तरह होगा, लेकिन यह वास्तव में अच्छी तरह से काम करता है। धन्यवाद! – dkhaupt