2017-09-18 7 views
0

J'ai un modèle et sérialiseur comme ceci:Django REST Framework - optimisation sérialisation imbriqué d'un queryset

models.py

class CalendarEvent(BaseMixin): 
    title = models.TextField(blank=True, null=True) 

class CalendarEventReminder(BaseMixin): 
    event = models.ForeignKey(CalendarEvent, related_name = 'reminders') 
    minutes = models.CharField() 

class Meta: 
    managed = False 
    db_table = 'calendar_event_reminder' 

def __str__(self): 
    return self.minutes 

serializer.py

class CalendarEventSerializer(serializers.ModelSerializer): 
    reminders = serializers.StringRelatedField(many=True) 

    class Meta: 
     model = CalendarEvent 
     fields = ('title', 'reminders') 

À mon avis, Je fais ce qui suit:

def test(request): 
    #... 
    event = CalendarEvent.objects.filter(id__in = [930, 935]) 
    serializer = CalendarEventSerializer(event, many = True) 
    print (serializer.data) 
    #... 

Lorsque j'ouvre la barre d'outils de débogage, je vois que la base de données rencontre deux fois la table des rappels pour chacun des événements du calendrier.

enter image description here

La question est, comment ce comportement pourrait être optimisé.

Répondre

0

La façon la plus straight-forward serait préchargement les CalendarEventReminders des AgendaManifestations à votre avis:

# views.py 
def get(request): 
    event = CalendarEvent.objects.filter(id__in = [930, 935]) \ 
           .prefetch_related('reminders') 
    # ... 

Cela précharger tous CalendarEventReminders tout en obtenant les AgendaManifestations. Notez que cela ne déclenchera pas une jointure sql comme select_related() ferait. Nous ne pouvons pas utiliser select_related() dans ce cas parce que nous suivons la relation en arrière. :)

Consultez le Django Docs regarding prefetch_related.

+0

Eh bien, je connais 'prefetch_related'. La question était, comment puis-je le faire via des sérialiseurs imbriqués. Sont-ils destinés à ne sérialiser que les objets et non les ensembles de requêtes? –

+0

Oui, les sérialiseurs ne sérialisent que les objets. Le traitement de votre requête est fait à votre vue. Vos requêtes telles que vues dans la barre d'outils de débogage sont déclenchées par de simples appels '__getitem__' à votre jeu de requête, c'est pourquoi' prefetch_related' va éliminer ces requêtes ou plutôt, les récupérer toutes en même temps au début. – olieidel