Files
chunyu_project/tool/views/tool_favorite_view.py
T

111 lines
3.8 KiB
Python

from django.http import JsonResponse
from adrf.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.parsers import JSONParser
from asgiref.sync import sync_to_async
from ..models import Tool, ToolFavorite
class ToolFavoriteToggleView(APIView):
permission_classes = [IsAuthenticated]
parser_classes = [JSONParser]
async def post(self, request, tool_id):
# 事务段(get_or_create + delete + count)整体放入同步函数,sync_to_async 执行保证原子性
def _toggle_in_txn():
from django.db import transaction
with transaction.atomic():
try:
tool = Tool.objects.get(pk=tool_id, is_enabled=True)
except Tool.DoesNotExist:
return None
favorite, created = ToolFavorite.objects.get_or_create(
user=request.user,
tool=tool
)
if not created:
favorite.delete()
is_favorite = False
message = '已取消收藏'
else:
is_favorite = True
message = '已添加收藏'
favorite_count = ToolFavorite.objects.filter(tool=tool).count()
return {
'tool_id': tool.id,
'is_favorite': is_favorite,
'favorite_count': favorite_count,
'message': message,
}
result = await sync_to_async(_toggle_in_txn)()
if result is None:
return JsonResponse({'success': False, 'error': '工具不存在'}, status=404)
return JsonResponse({
'success': True,
'data': {
'id': result['tool_id'],
'is_favorite': result['is_favorite'],
'favorite_count': result['favorite_count']
},
'message': result['message']
})
class ToolFavoriteListView(APIView):
permission_classes = [IsAuthenticated]
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')]
data = []
for fav in favorites:
favorite_count = await ToolFavorite.objects.filter(tool=fav.tool).acount()
data.append({
'id': fav.tool.id,
'name': fav.tool.name,
'description': fav.tool.description,
'icon': fav.tool.icon,
'url_path': fav.tool.url_path,
'color': fav.tool.color,
'category': fav.tool.category.id if fav.tool.category else None,
'category_name': fav.tool.category.name if fav.tool.category else '',
'is_favorite': True,
'favorite_count': favorite_count,
'created_at': fav.created_at.isoformat()
})
return JsonResponse({
'success': True,
'data': {
'count': len(data),
'results': data
}
})
class ToolFavoriteStatusView(APIView):
permission_classes = [IsAuthenticated]
async def get(self, request, tool_id):
is_favorite = await ToolFavorite.objects.filter(
user=request.user,
tool_id=tool_id
).aexists()
favorite_count = await ToolFavorite.objects.filter(tool_id=tool_id).acount()
return JsonResponse({
'success': True,
'data': {
'tool_id': tool_id,
'is_favorite': is_favorite,
'favorite_count': favorite_count
}
})