Как я могу кэшировать результат SerializerMethodField
У меня есть сериализатор:
class OrderItemResponseSerializer(serializers.ModelSerializer):
prepack_qty = serializers.SerializerMethodField()
product_description = serializers.SerializerMethodField()
class Meta:
model = OrderItem
fields = (
"product",
"qty_ordered",
"qty_approved",
"status",
"prepack_qty",
"product_description"
)
def get_prepack_qty(self, obj):
return obj.product.prepack_quantity
def get_product_description(self, obj):
return obj.product.product_description
Когда я делаю get запрос к /orders, я делаю много sql запросов к базе данных, потому что разные заказы могут содержать один и тот же продукт. Как я могу кэшировать результат методов get_prepack_qty и get_product_description? Я пытался использовать @cached_property следующим образом:
class OrderItem(models.Model):
...
@cached_property
def item_product_description(self):
return self.product.product_description
но количество запросов к базе данных осталось прежним.
Лучше использовать, например, Redis для кэширования результата
Посмотрите этот учебник для лучшего понимания
Желаю удачи
Во-первых, я должен сказать, что то, что вы реализовали в этом куске кода ниже:
...
@cached_property
def item_product_description(self):
return self.product.product_description
И использование @cached_property
само по себе не кэширует данные для вас, вы просто создали свойство в модели для метода сериализатора get_product_description
, И это совсем не уменьшает объем и количество ваших запросов к базе данных; Конечно, вам нужен метод .bind()
в вашем методе сериализатора, как показано ниже:
class BlobSerializer(SerializerCacheMixin, serializers.Serializer):
blobs = serializers.SerializerMethodField()
def get_blobs(self, instance):
# recursive serializer
serializer = self.__class__(instance.results, many=True)
serializer.bind('*', self)
return serializer.data
Но для того, чтобы кэшировать результат этого метода Как вы спросили в своем вопросе, есть хороший проект в Pypi под названием drf-serializer-cache
вы можете легко использовать его для этой цели, например, следующий кусок кода взят из документа этого проекта :
from drf_serializer_cache import SerializerCacheMixin from rest_framework import serializer class ResultSerializer(SerializerCacheMixin, serializers.Serializer): results = serializers.SerializerMethodField() def get_results(self, instance): # recursive serializer serializer = self.__class__(instance.results, many=True) serializer.bind('*', self) # bind call is essential for >efficient cache! return serializer.data
Также, если вы хотите реализовать его самостоятельно в своем проекте, просмотр реализации SerializerCacheMixin
объекта в этом проекте может помочь вам во многом или даже использовать его напрямую.
You can leverage Django's cache framework to cache the result of a SerializerMethodField. It would look something like this:
from django.core.cache import cache
class MySerializer(serializers.Serializer):
my_field = serializers.SerializerMethodField()
def get_my_field(self, obj):
# Get cached value
value = cache.get("my_field_%s" % obj.pk)
if value is None:
# Value is not cached, compute it
value = ...
# Cache the value
cache.set("my_field_%s" % obj.pk, value, 3600)
return value
This will cache the result of the field for 1 hour (3600 seconds), using a cache key that depends on the object's primary key.
You can of course adapt the caching logic to your exact use case.