How to optimize the django rest serializer with me

2019-07-30 13:08发布

问题:

I'm using django rest framework for social network like site. But serializer is dead slow.

Models:

class Profile(models.Model):
    user=models.OneToOneField(User)
    name=models.CharField(max_length=40)
    fb_id=models.CharField(max_length=40)
    profile_pic=models.TextField()
    country=models.CharField(max_length=40,null=True,blank=True)
    dob=models.DateField()
    favorite_artist=models.CharField(max_length=40,null=True,blank=True)
    favorite_album=models.CharField(max_length=40,null=True,blank=True)
    favorite_song=models.CharField(max_length=40,null=True,blank=True)
    is_private=models.BooleanField(default=False)
    following=models.IntegerField(default=0)
    followers=models.IntegerField(default=0)


class Post(models.Model):
    user=models.ForeignKey(User,related_name='user')
    likes=models.IntegerField(default=0)
    comments=models.IntegerField(default=0)
    created = models.DateTimeField(auto_now_add=True)
    content=models.TextField()
    song_name=models.CharField(max_length=100)
    song_album=models.CharField(max_length=100)
    song_artist=models.CharField(max_length=100)    

Here's my serializers:

class ProfileBasicSerializer(serializers.ModelSerializer):
    class Meta: 
        model=Profile 
        fields=('name','profile_pic')


class UserBasicSerializer(serializers.ModelSerializer):
    profile=ProfileBasicSerializer()
    is_following=serializers.SerializerMethodField()

    class Meta:
        model=get_user_model() 
        fields=('username','profile','is_following')

    def get_is_following(self,obj):
        try:
            Follow.objects.get(user=self.context['request'].user,to_user=obj)
            return'following'
        except Follow.DoesNotExist:
            try: 
                Request.objects.get(user=self.context['request'].user,to_user=obj)
                return 'requested'
            except Request.DoesNotExist:
                return 'not'

    class PostSerializer(serializers.ModelSerializer):
        liked=serializers.SerializerMethodField()
        user=serializers.SerializerMethodField()    
        class Meta: 
            model=Post
            fields=('id','user','content','song_name','song_artist','song_album','likes','comments','created','liked')

        def get_liked(self,obj):
            try: 
                Like.objects.get(post=obj,user=self.context['request'].user)
                return 'true'
            except Like.DoesNotExist: 
                return 'false'   

        def get_user(self,obj): 
            user=obj.user 
            serializer=UserBasicSerializer(user,context=self.context)
            return serializer.data

And I created a test view:

@api_view(['GET'])
@authentication_classes((TokenAuthentication,))
@permission_classes((IsAuthenticated,))
def test(request):
    query_set=Post.objects.all()
    serializer=PostSerializer(query_set,many=True,context={'request':request})         
    return Response(serializer.data,  status=status.HTTP_202_ACCEPTED) 

This view returns posts along with the details whether the querying user liked the given post and some details about the user who posted

Sample response for post serializer is:

[
  {
    "id": 1,
    "user": {
      "username": "jithu",
      "profile": {
        "name": "Raju",
        "profile_pic": "http://google.com"
      },
      "is_following": "not"
    },
    "content": "I.m feeling happy....",
    "song_name": "vgdhbnm",
    "song_artist": "vgdhbnm",
    "song_album": "vgdhbnm",
    "likes": 0,
    "comments": 0,
    "created": "2016-05-29T05:53:54.656951Z",
    "liked": "false"
  }

The database backend is postgresql and contains only 4000 post records still this serializer is very slow. I read something about prefetch. But I don't know how to use in this case... Thanks in advance!