Reputation: 614
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
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
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
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