django-oscar-api 与 Django 的 UpdateCacheMiddleware 冲突:{TypeError}cannot pickle '_io.BufferedReader' object
django-oscar-api conflict with Django's UpdateCacheMiddleware: {TypeError}cannot pickle '_io.BufferedReader' object
我在 django-oscar 项目中用 django-oscar-api 实现了 django 的 per site cache。我使用 LocMemCache 作为缓存后端。
在将 django.middleware.cache.UpdateCacheMiddleware
添加到我的中间件之前,一切正常,我可以像这样向“篮子”端点发出请求并返回 200 响应:
import requests
session = session.Session()
r_basket = session.get("http://127.0.0.1:8000/api/basket/")
添加每个站点缓存后,响应的状态代码为 500。我对其进行了调试,但在 UpdateCacheMiddleware
中失败并出现以下错误:{TypeError}cannot pickle '_io.BufferedReader' object
.
其他端点似乎工作正常,但我还没有对它们进行全部测试。
该错误也可以在新安装的 django-oscar sandbox 上重现。我 pip 安装了 django-oscar-api 并将其添加到已安装的应用程序中,MIDDLEWARE 设置如下所示:
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',
# 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',
# Ensure a valid basket is added to the request instance for every request
'oscar.apps.basket.middleware.BasketMiddleware',
]
我的包版本是 Django v.3.2.9、django-oscar v.2.2 或 3.0、django-oscar-api v.2.1.1.
什么对象不能被 pickle?或者中间件的顺序可能有误?
回溯:
[2021-11-13 08:43:33,256] Internal Server Error: /api/basket/
Traceback (most recent call last):
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
response = self.process_response(request, response)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/middleware/cache.py", line 111, in process_response
response.add_post_render_callback(
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/template/response.py", line 92, in add_post_render_callback
callback(self)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/middleware/cache.py", line 112, in <lambda>
lambda r: self.cache.set(cache_key, r, timeout)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/debug_toolbar/panels/cache.py", line 39, in wrapped
value = method(self, *args, **kwargs)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/debug_toolbar/panels/cache.py", line 94, in set
return self.cache.set(*args, **kwargs)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/core/cache/backends/locmem.py", line 56, in set
pickled = pickle.dumps(value, self.pickle_protocol)
TypeError: cannot pickle '_io.BufferedReader' object
预期响应
{'id': 1,
'owner': None,
'status': 'Open',
'lines': 'http://127.0.0.1:8000/api/baskets/1/lines/',
'url': 'http://127.0.0.1:8000/api/baskets/1/',
'total_excl_tax': '0.00',
'total_excl_tax_excl_discounts': '0.00',
'total_incl_tax': '0.00',
'total_incl_tax_excl_discounts': '0.00',
'total_tax': '0.00',
'currency': None,
'voucher_discounts': [],
'offer_discounts': [],
'is_tax_known': True}
查看:oscarapi.views.basket.BasketView
您需要确保在您的设置中UpdateCacheMiddleware 在SessionMiddleware 和LocaleMiddleware 之前。 DOCS
FetchFromCacheMiddleware 需要在那些中间件之后,可以留在原处
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# Moved UpdateCacheMiddleware to here
'django.middleware.cache.UpdateCacheMiddleware',
'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',
# Allow languages to be selected
'django.middleware.locale.LocaleMiddleware',
'django.middleware.http.ConditionalGetMiddleware',
'django.middleware.common.CommonMiddleware',
# per site caching
'django.middleware.cache.FetchFromCacheMiddleware',
# Ensure a valid basket is added to the request instance for every request
'oscar.apps.basket.middleware.BasketMiddleware',
]
我在 django-oscar 项目中用 django-oscar-api 实现了 django 的 per site cache。我使用 LocMemCache 作为缓存后端。
在将 django.middleware.cache.UpdateCacheMiddleware
添加到我的中间件之前,一切正常,我可以像这样向“篮子”端点发出请求并返回 200 响应:
import requests
session = session.Session()
r_basket = session.get("http://127.0.0.1:8000/api/basket/")
添加每个站点缓存后,响应的状态代码为 500。我对其进行了调试,但在 UpdateCacheMiddleware
中失败并出现以下错误:{TypeError}cannot pickle '_io.BufferedReader' object
.
其他端点似乎工作正常,但我还没有对它们进行全部测试。 该错误也可以在新安装的 django-oscar sandbox 上重现。我 pip 安装了 django-oscar-api 并将其添加到已安装的应用程序中,MIDDLEWARE 设置如下所示:
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',
# 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',
# Ensure a valid basket is added to the request instance for every request
'oscar.apps.basket.middleware.BasketMiddleware',
]
我的包版本是 Django v.3.2.9、django-oscar v.2.2 或 3.0、django-oscar-api v.2.1.1.
什么对象不能被 pickle?或者中间件的顺序可能有误?
回溯:
[2021-11-13 08:43:33,256] Internal Server Error: /api/basket/
Traceback (most recent call last):
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
response = self.process_response(request, response)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/middleware/cache.py", line 111, in process_response
response.add_post_render_callback(
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/template/response.py", line 92, in add_post_render_callback
callback(self)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/middleware/cache.py", line 112, in <lambda>
lambda r: self.cache.set(cache_key, r, timeout)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/debug_toolbar/panels/cache.py", line 39, in wrapped
value = method(self, *args, **kwargs)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/debug_toolbar/panels/cache.py", line 94, in set
return self.cache.set(*args, **kwargs)
File "/home/victor/PycharmProjects/virtual_environments/django-oscar-sandbox/lib/python3.8/site-packages/django/core/cache/backends/locmem.py", line 56, in set
pickled = pickle.dumps(value, self.pickle_protocol)
TypeError: cannot pickle '_io.BufferedReader' object
预期响应
{'id': 1,
'owner': None,
'status': 'Open',
'lines': 'http://127.0.0.1:8000/api/baskets/1/lines/',
'url': 'http://127.0.0.1:8000/api/baskets/1/',
'total_excl_tax': '0.00',
'total_excl_tax_excl_discounts': '0.00',
'total_incl_tax': '0.00',
'total_incl_tax_excl_discounts': '0.00',
'total_tax': '0.00',
'currency': None,
'voucher_discounts': [],
'offer_discounts': [],
'is_tax_known': True}
查看:oscarapi.views.basket.BasketView
您需要确保在您的设置中UpdateCacheMiddleware 在SessionMiddleware 和LocaleMiddleware 之前。 DOCS
FetchFromCacheMiddleware 需要在那些中间件之后,可以留在原处
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# Moved UpdateCacheMiddleware to here
'django.middleware.cache.UpdateCacheMiddleware',
'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',
# Allow languages to be selected
'django.middleware.locale.LocaleMiddleware',
'django.middleware.http.ConditionalGetMiddleware',
'django.middleware.common.CommonMiddleware',
# per site caching
'django.middleware.cache.FetchFromCacheMiddleware',
# Ensure a valid basket is added to the request instance for every request
'oscar.apps.basket.middleware.BasketMiddleware',
]