2

I have a model and serializer like this:

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')

In my view, I do the following:

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

When I open the Debug Toolbar, I see that the database hits reminders table twice for each of the calendar events.

enter image description here

The question is, how this behavior could be optimized.

1 Answer 1

2

The most straight-forward way would be prefetching the CalendarEventReminders of the CalendarEvents in your view:

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

This will prefetch all CalendarEventReminders while getting the CalendarEvents.

Note that this will not trigger a sql join like select_related() would do. We can't use select_related() in this case because we're following the relation backwards. :)

Check out the Django Docs regarding prefetch_related.

Sign up to request clarification or add additional context in comments.

2 Comments

Well, I know about prefetch_related. The question was, how can I do it via nested serializers. Are they intented to only serialize objects and not querysets ?
Yes, serializers only serialize objects. The handling of your queryset is done in your view. Your queries as seen in the debug toolbar are triggered by simple __getitem__ calls to your queryset, that's why prefetch_related will eliminate those queries or rather, fetch them all at once at the beginning.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.