user1518217
user1518217

Reputation: 614

Django REST Framework: how to cache the result of SerializerMethodField?

I have a SerializerMethodField that make some heavy computation. I also use the same method into another SerializerMethodField of the same serializer. How can I cache the result of the first one, so I run only once the heavy computation?

Upvotes: 4

Views: 2469

Answers (3)

radtek
radtek

Reputation: 36260

I don't think you will be able to use the cached property or cache on the function itself on the SerializerMethodField but you can cache the result yourself at the instance level and then use the result if its set i.e.

from rest_framework import serializers

class WeatherLocationSerializer(serializers.ModelSerializer):
   
    city = serializers.SerializerMethodField()

    cached_city = None


    def get_city(self, obj, include_counties=False):
        if self.cached_city:
            return self.cached_city
        
        # Do your expensive calculation and parsing here
        self.cached_city = self.obj['city']
        
        return self.cached_city

I'm using a very old version of drf (djangorestframework==3.9.4) but this sort of class instance caching can be applied. Another way is to not use SerializerMethodField and instead do your parsing and calculations once in def to_representation(self, obj): and store the parts that repeat into a variable instead. That would look something like:

from rest_framework import serializers

class WeatherLocationSerializer(serializers.ModelSerializer):
    
    def get_city(self, obj):
        # This could be an expensive calculation this is just an example
        return obj['city']
    
    def to_representation(self, obj):
        data = super().to_representation(obj)
    
        city = self.get_city(obj)
        
        # Now use your cached value of city where needed
        data['city'] = city
        data['same_city'] = city
        
        return data

Upvotes: 1

bnmounir
bnmounir

Reputation: 91

With python version 3.8 and above you can now use the built-in caching decorators @cache and @cached_property

https://docs.python.org/3/library/functools.html#functools.cache

Upvotes: 1

arjunattam
arjunattam

Reputation: 2819

Since the computation is common between two methods of the same serializer, you can use the cached_property decorator. This will cache the result of the method on the model instance, and the result will persist as long as the instance does.

from django.utils.functional import cached_property

class Person(models.Model):

    @cached_property
    def friends(self):
        ...

Upvotes: 2

Related Questions