feat: ADRF async views (phase1) + native async serializers (phase2) + async cache infra

This commit is contained in:
async-upgrade
2026-09-06 14:26:17 +08:00
parent 9a6577f71e
commit 8f488fcaaa
55 changed files with 2224 additions and 1513 deletions
+30 -27
View File
@@ -1,5 +1,5 @@
from django.http import JsonResponse
from rest_framework.views import APIView
from adrf.views import APIView
from rest_framework import status
from rest_framework.permissions import AllowAny, IsAuthenticated
from django.db.models import Count, Q
@@ -19,8 +19,8 @@ class ToolCategoryListView(APIView):
tags=['工具'],
responses={200: success_response}
)
def get(self, request):
categories = ToolCategory.objects.prefetch_related('tools').all()
async def get(self, request):
categories = [c async for c in ToolCategory.objects.prefetch_related('tools').all()]
serializer = ToolCategorySerializer(categories, many=True)
return JsonResponse({
'success': True,
@@ -42,7 +42,7 @@ class ToolListView(APIView):
],
responses={200: success_response}
)
def get(self, request):
async def get(self, request):
category_id = request.query_params.get('category_id')
enabled_only = request.query_params.get('enabled_only', 'true')
ordering = request.query_params.get('ordering', '')
@@ -68,18 +68,19 @@ class ToolListView(APIView):
else:
tools = tools.order_by('sort_order', '-created_at')
serializer = ToolSerializer(tools, many=True)
tool_list = [t async for t in tools]
serializer = ToolSerializer(tool_list, many=True)
data = serializer.data
# 构建 favorites_count 映射
favorites_count_map = {
t.id: t.annotated_favorites_count for t in tools
t.id: t.annotated_favorites_count for t in tool_list
}
if request.user.is_authenticated:
favorite_tool_ids = set(
ToolFavorite.objects.filter(user=request.user).values_list('tool_id', flat=True)
)
favorite_tool_ids = set([
tid async for tid in ToolFavorite.objects.filter(user=request.user).values_list('tool_id', flat=True)
])
for item in data:
item['is_favorited'] = item['id'] in favorite_tool_ids
item['favorites_count'] = favorites_count_map.get(item['id'], 0)
@@ -106,18 +107,18 @@ class ToolDetailView(APIView):
],
responses={200: success_response, 404: not_found_response}
)
def get(self, request, pk):
async def get(self, request, pk):
try:
tool = Tool.objects.select_related('category').get(pk=pk, is_enabled=True)
tool = await Tool.objects.select_related('category').aget(pk=pk, is_enabled=True)
serializer = ToolSerializer(tool)
data = serializer.data
if request.user.is_authenticated:
data['is_favorited'] = ToolFavorite.objects.filter(
data['is_favorited'] = await ToolFavorite.objects.filter(
user=request.user, tool=tool
).exists()
).aexists()
else:
data['is_favorited'] = False
data['favorites_count'] = ToolFavorite.objects.filter(tool=tool).count()
data['favorites_count'] = await ToolFavorite.objects.filter(tool=tool).acount()
return JsonResponse({
'success': True,
'data': data
@@ -141,20 +142,20 @@ class ToolFavoriteToggleView(APIView):
],
responses={200: success_response, 401: unauthorized_response, 404: not_found_response}
)
def post(self, request, pk):
tool = Tool.objects.filter(pk=pk, is_enabled=True).first()
async def post(self, request, pk):
tool = await Tool.objects.filter(pk=pk, is_enabled=True).afirst()
if not tool:
return JsonResponse(
{'success': False, 'error': '工具不存在'},
status=status.HTTP_404_NOT_FOUND
)
fav, created = ToolFavorite.objects.get_or_create(user=request.user, tool=tool)
fav, created = await ToolFavorite.objects.aget_or_create(user=request.user, tool=tool)
if not created:
fav.delete()
await fav.adelete()
is_favorited = False
else:
is_favorited = True
favorites_count = ToolFavorite.objects.filter(tool=tool).count()
favorites_count = await ToolFavorite.objects.filter(tool=tool).acount()
return JsonResponse({
'success': True,
'data': {
@@ -174,17 +175,19 @@ class ToolFavoriteListView(APIView):
tags=['工具'],
responses={200: success_response, 401: unauthorized_response}
)
def get(self, request):
favorites = ToolFavorite.objects.select_related('tool', 'tool__category').filter(
async def get(self, request):
favorites = [fav async for fav in ToolFavorite.objects.select_related(
'tool', 'tool__category'
).filter(
user=request.user,
tool__is_enabled=True
).order_by('-created_at')
).order_by('-created_at')]
result = []
for fav in favorites:
tool_data = ToolSerializer(fav.tool).data
tool_data['is_favorited'] = True
tool_data['favorites_count'] = ToolFavorite.objects.filter(tool=fav.tool).count()
tool_data['favorites_count'] = await ToolFavorite.objects.filter(tool=fav.tool).acount()
result.append(tool_data)
return JsonResponse({
@@ -206,13 +209,13 @@ class ToolUsageIncrementView(APIView):
],
responses={200: success_response, 404: not_found_response}
)
def post(self, request, pk):
async def post(self, request, pk):
try:
tool = Tool.objects.get(pk=pk, is_enabled=True)
tool = await Tool.objects.aget(pk=pk, is_enabled=True)
# 使用F()表达式避免竞态条件
from django.db.models import F
Tool.objects.filter(pk=pk).update(usage_count=F('usage_count') + 1)
tool.refresh_from_db()
await Tool.objects.filter(pk=pk).aupdate(usage_count=F('usage_count') + 1)
await tool.arefresh_from_db()
return JsonResponse({
'success': True,
'data': {