fix: never_cache sync wrapper broke async dispatch - add async_never_cache_dispatch (wallet/login_record/tasks)

This commit is contained in:
async-upgrade
2026-09-06 16:27:17 +08:00
parent cf79c92927
commit 50ae676bb2
4 changed files with 45 additions and 10 deletions
+4 -3
View File
@@ -6,6 +6,7 @@ from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from datetime import timedelta
from utils.async_decorators import async_never_cache_dispatch
from utils.response_codes import (
ResponseCode,
create_standardized_response,
@@ -18,7 +19,7 @@ from drf_yasg import openapi
from chunyu_project.common_schemas import success_response, error_response, unauthorized_response, not_found_response
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class LoginRecordListAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -87,7 +88,7 @@ class LoginRecordListAPIView(APIView):
)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class LoginRecordDeleteAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -117,7 +118,7 @@ class LoginRecordDeleteAPIView(APIView):
)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class LoginRecordClearAPIView(APIView):
permission_classes = [IsAuthenticated]
+5 -4
View File
@@ -10,6 +10,7 @@ from django.views.decorators.cache import never_cache
from datetime import timedelta
import logging
from utils.async_decorators import async_never_cache_dispatch
from utils.response_codes import (
ResponseCode,
create_standardized_response,
@@ -112,7 +113,7 @@ def check_level_up(user_level):
return leveled_up
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class TaskListAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -195,7 +196,7 @@ class TaskListAPIView(APIView):
)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class TaskTrackAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -249,7 +250,7 @@ class TaskTrackAPIView(APIView):
)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class TaskClaimAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -377,7 +378,7 @@ class TaskClaimAPIView(APIView):
)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class UserLevelAPIView(APIView):
permission_classes = [IsAuthenticated]
+4 -3
View File
@@ -11,6 +11,7 @@ import logging
from asgiref.sync import sync_to_async
from utils.async_decorators import async_never_cache_dispatch
from utils.response_codes import (
ResponseCode,
create_standardized_response,
@@ -25,7 +26,7 @@ from chunyu_project.common_schemas import success_response, error_response, unau
logger = logging.getLogger(__name__)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class WalletBalanceAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -222,7 +223,7 @@ async def track_checkin_task(user):
logger.error(f'签到任务进度更新失败: {e}')
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class CheckinStatusAPIView(APIView):
permission_classes = [IsAuthenticated]
@@ -277,7 +278,7 @@ class CheckinStatusAPIView(APIView):
)
@method_decorator(never_cache, name='dispatch')
@async_never_cache_dispatch
class CheckinAPIView(APIView):
permission_classes = [IsAuthenticated]
+32
View File
@@ -0,0 +1,32 @@
"""
异步友好的 never_cache 类装饰器
================================
替代 `@method_decorator(never_cache, name='dispatch')`。
背景:@method_decorator 生成同步包装器,在 adrf 的 async dispatch 返回的协程上
调用 add_never_cache_headers 会抛 AttributeError('coroutine' object has no
attribute 'has_header')。本装饰器兼容同步/异步 dispatch,语义与 never_cache 一致。
用法(作为类装饰器):
@async_never_cache_dispatch
class WalletBalanceAPIView(APIView):
...
"""
import asyncio
from django.utils.cache import add_never_cache_headers
def async_never_cache_dispatch(cls):
orig_dispatch = cls.dispatch
async def dispatch(self, request, *args, **kwargs):
response = orig_dispatch(self, request, *args, **kwargs)
if asyncio.iscoroutine(response):
response = await response
if response is not None and hasattr(response, "has_header"):
add_never_cache_headers(response)
return response
cls.dispatch = dispatch
return cls