django-oscar-api与Django UpdateCacheMiddleware冲突报pickle序列化错误
问题原因及解决方法
无法序列化的对象说明
报错里提到的不能被pickle序列化的是oscarapi.views.basket.BasketView返回的DRF响应对象中附带的_io.BufferedReader类型流句柄。该接口返回的虽然是标准JSON结构,但django-oscar-api内部为了兼容多场景响应处理,会给Response对象附加未被显式消费的二进制流属性,LocMemCache序列化整个Response对象时就会触发该错误。中间件配置顺序确实有误
你当前的oscar.apps.basket.middleware.BasketMiddleware放在了全站缓存中间件之后,请求进入缓存逻辑时还没有完成当前用户购物车对象的初始化,缓存中间件直接尝试序列化未完全处理的响应就会报错。需要把BasketMiddleware移到全站缓存中间件的上方,调整后的顺序参考:
MIDDLEWARE = [ 'debug_toolbar.middleware.DebugToolbarMiddleware', 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', # 购物车中间件移到缓存逻辑之前 'oscar.apps.basket.middleware.BasketMiddleware', # Allow languages to be selected 'django.middleware.locale.LocaleMiddleware', 'django.middleware.http.ConditionalGetMiddleware', 'django.middleware.common.CommonMiddleware', # per site caching 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', ]
- 额外业务适配建议
购物车属于用户私有的动态接口,每个用户的购物车数据完全不同,本身就不适合用全站缓存做统一缓存,即使顺序调整后不报错,缓存该接口也会返回错误的用户数据。你可以给BasketView加上@never_cache装饰器,或者在settings里配置全站缓存的排除路径,跳过这类用户私有接口的缓存逻辑。
内容的提问来源于stack exchange,提问作者movileanuv
相关产品推荐
相关产品推荐

