ModelSerializer is extremely slow in Django REST framework

I use Django REST for my API, and yesterday I wanted to see how it works for big data. I found this tutorial on how to profile your queries (written by Tom Christie), and I found that for 10,000 users, my request hit 2: 20 minutes.

Most of the time we spent on serializing objects (about 65%), so I was wondering what can I do to speed up the process?

My user model actually extends the django model by default, so use . values ​​() does not work, because I also do not get the nested model (although it is much faster).

Any help would be greatly appreciated :)

Edit

I already use .select_related () when receiving my request, and it improved my time, but only by a few seconds. The total number of queries is 10, so the problem is not related to access to the database.

In addition, I use .defer () to avoid fields that I do not need in this query. It also provided a slight improvement, but not enough.

Edit # 2

Models

from django.contrib.auth.models import User
from django.db.models import OneToOneField
from django.db.models import ForeignKey

from userena.models import UserenaLanguageBaseProfile
from django_extensions.db.fields import CreationDateTimeField
from django_extensions.db.fields import ModificationDateTimeField

from mycompany.models import MyCompany


class UserProfile(UserenaLanguageBaseProfile):
    user = OneToOneField(User, related_name='user_profile')
    company = ForeignKey(MyCompany)
    created = CreationDateTimeField(_('created'))
    modified = ModificationDateTimeField(_('modified'))

Serializers

from django.contrib.auth.models import User

from rest_framework import serializers

from accounts.models import UserProfile


class UserSerializer(serializers.ModelSerializer):
    last_login = serializers.ReadOnlyField()
    date_joined = serializers.ReadOnlyField()
    is_active = serializers.ReadOnlyField()

    class Meta:
        model = User
        fields = (
            'id',
            'last_login',
            'username',
            'first_name',
            'last_name',
            'email',
            'is_active',
            'date_joined',
        )


class UserProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = UserProfile
        fields = (
            'id',
            'user',
            'mugshot',
            'language',
        )

Views

class UserProfileList(generics.GenericAPIView,
                      mixins.ListModelMixin,
                      mixins.CreateModelMixin):

    serializer_class = UserProfileSerializer
    permission_classes = (UserPermissions, )

    def get_queryset(self):
        company = self.request.user.user_profile.company
        return UserProfile.objects.select_related().filter(company=company)

    @etag(etag_func=UserListKeyConstructor())
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
+4
source share
2 answers

N + 1. , , . , .select_related .prefetch_related get_queryset, .

, Django , Django REST, .

, , , Django .

+5

, , , , ... , ...

,

select_related()

, . ,

prefetch_related('user_profile')

, select_related " ", prefetch_related . , " " .

, . get_queryset() , , , :

def get_queryset(self):
    return UserProfile.objects.prefetch_related('user_profile').all()
+1

All Articles