如何使用查询参数让服务器删除API调用缓存(django,DRF)

如何使用查询参数让服务器删除API调用缓存(django,DRF),django,caching,memcached,django-rest-framework,Django,Caching,Memcached,Django Rest Framework,我正在使用Django Rest框架和DRF扩展() 我有一个API调用/user/:id/products,它提供了用户可以访问的产品的完整列表。因为这是一个昂贵的查询,所以我将根据方法id、格式、语言、用户和检索SQL查询对其进行缓存 我有另一个API调用/支付,它处理我们所有的付款。产品ID是该API调用的POST参数 用户付费后,它会立即将他们引导到产品页面——但由于产品查询是缓存的,因此它仍然显示旧的产品列表,而不是他们刚购买的新产品的更新列表。我知道cache.delete方法,但是

我正在使用Django Rest框架和DRF扩展()

我有一个API调用/user/:id/products,它提供了用户可以访问的产品的完整列表。因为这是一个昂贵的查询,所以我将根据方法id、格式、语言、用户和检索SQL查询对其进行缓存

我有另一个API调用/支付,它处理我们所有的付款。产品ID是该API调用的POST参数

用户付费后,它会立即将他们引导到产品页面——但由于产品查询是缓存的,因此它仍然显示旧的产品列表,而不是他们刚购买的新产品的更新列表。我知道
cache.delete
方法,但是从
/pay
获取密钥很困难,因为它是一个完全不同的API调用

我想做的是在
/user/:id/products
API调用中添加一个参数
force\u refresh
,如果存在该参数,将计算哈希键,就像
force\u refresh
参数不存在一样,然后清除该键的缓存。然而,我在drf扩展的缓存框架中的
KeyConstructor
中找不到合适的位置来坚持这一点让服务器知道删除此查询的缓存的最佳方法是什么?

我想做的是将参数force_refresh添加到/user/:id/products API调用中

我认为这不是个好主意。如果您的客户提出了
/pay
请求,然后使用自己的路由到
/user/:id/products
,该怎么办?使用
force_refresh
属性,您正在为请求添加状态,它不再是幂等的

如果您有高读速率和低写速率,我建议您根据保存后信号,使用全局缓存失效来创建

如果你想使缓存失效更具体,我建议你去规范化你的用户模型。例如:

class User(UserBaseModel):
    ...
    products_updated_date = models.DateTimeField()
CACHES = {
    "default": {
        "BACKEND": "redis_cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/0"
    }
}

REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 20
您应该在每次付款时更新
产品\u更新\u日期

class UserViewSet(CacheResponseMixin, ReadOnlyModelViewSet):
    ...
    @action('pay')
    def pay(self):
        ...
        self.request.user.products_updated_date = now()
        self.request.user.save()
        ...
最后,您应该使用用户的
products\u updated\u date
字段用法创建自定义密钥位:

from rest_framework_extensions.key_constructor.bits import (
    KeyBitBase
)

class UserProductsUpdatedKeyBit(KeyBitBase):
    def get_data(self, **kwargs):
        request = kwargs['request']
        if (hasattr(request, 'user') and 
            request.user and 
            request.user.is_authenticated()):
            return request.user.products_updated_date

您可以将
UserProductsUpdatedKeyBit
添加到
/user/:id/products
路由的密钥构造函数类。

使用DRF扩展缓存和所有GET参数作为ReadOnlyModelViewSet上的密钥哈希的示例

定义密钥构造函数(密钥哈希):

你的看法是:

class UserViewSet(ListCacheResponseMixin, viewsets.ReadOnlyModelViewSet):
    serializer_class = UserSerializer
    list_cache_key_func = QueryParamsKeyConstructor()
在settings.py中设置DRF扩展和django缓存设置,例如:

class User(UserBaseModel):
    ...
    products_updated_date = models.DateTimeField()
CACHES = {
    "default": {
        "BACKEND": "redis_cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/0"
    }
}

REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 20
}