from adrf.views import APIView from rest_framework.response import Response from rest_framework import status from django.db.models import Q from asgiref.sync import sync_to_async from ..models import Blacklist, FUser from ..serializers.user_serializers import BlacklistSerializer from utils.response_codes import ( ResponseCode, create_standardized_response, create_standardized_error_response ) from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi from chunyu_project.common_schemas import success_response, error_response, unauthorized_response, not_found_response class BlacklistListAPIView(APIView): @swagger_auto_schema( tags=['黑名单'], operation_summary='获取黑名单列表', operation_description='获取当前用户的黑名单列表,支持搜索和分页', manual_parameters=[ openapi.Parameter('search', openapi.IN_QUERY, description='搜索关键词', type=openapi.TYPE_STRING), openapi.Parameter('page', openapi.IN_QUERY, description='页码', type=openapi.TYPE_INTEGER), openapi.Parameter('page_size', openapi.IN_QUERY, description='每页数量', type=openapi.TYPE_INTEGER), ], responses={200: success_response, 401: unauthorized_response}, ) async def get(self, request): queryset = Blacklist.objects.filter(user=request.user).select_related('blocked_user') search = request.query_params.get('search', '') if search: queryset = queryset.filter( Q(blocked_user__username__icontains=search) | Q(blocked_user__email__icontains=search) | Q(reason__icontains=search) ) page = int(request.query_params.get('page', 1)) page_size = int(request.query_params.get('page_size', 10)) total = await queryset.acount() start = (page - 1) * page_size end = start + page_size items = [item async for item in queryset[start:end]] serializer = BlacklistSerializer(items, many=True) return create_standardized_response( data={ 'results': await serializer.adata, 'total': total, 'page': page, 'page_size': page_size, 'total_pages': (total + page_size - 1) // page_size }, code=ResponseCode.SUCCESS, status_code=status.HTTP_200_OK ) class BlacklistAddAPIView(APIView): @swagger_auto_schema( tags=['黑名单'], operation_summary='添加黑名单', operation_description='将指定用户添加到黑名单', request_body=BlacklistSerializer, responses={201: success_response, 400: error_response, 401: unauthorized_response}, ) async def post(self, request): serializer = BlacklistSerializer( data=request.data, context={'request': request} ) # 校验器内部含同步 ORM 查询(validate_blocked_user_id / validate),线程池兜底 if not await sync_to_async(serializer.is_valid)(): errors = serializer.errors first_error = '' for field, msgs in errors.items(): if isinstance(msgs, list) and msgs: first_error = str(msgs[0]) break return create_standardized_error_response( data=errors, code=ResponseCode.PARAMETER_ERROR, message=first_error or '参数异常', status_code=status.HTTP_400_BAD_REQUEST ) blacklist = await serializer.asave() result_serializer = BlacklistSerializer(blacklist) return create_standardized_response( data=await result_serializer.adata, code=ResponseCode.SUCCESS, status_code=status.HTTP_201_CREATED ) class BlacklistCheckAPIView(APIView): @swagger_auto_schema( tags=['黑名单'], operation_summary='检查用户是否在黑名单中', operation_description='检查指定用户是否被当前用户加入黑名单', manual_parameters=[ openapi.Parameter('user_id', openapi.IN_PATH, description='用户ID', type=openapi.TYPE_INTEGER), ], responses={200: success_response, 401: unauthorized_response}, ) async def get(self, request, user_id): is_blocked = await Blacklist.objects.filter( user=request.user, blocked_user_id=user_id ).aexists() return create_standardized_response( data={'is_blocked': is_blocked}, code=ResponseCode.SUCCESS, status_code=status.HTTP_200_OK ) class BlacklistRemoveAPIView(APIView): @swagger_auto_schema( tags=['黑名单'], operation_summary='移除黑名单', operation_description='将指定用户从黑名单中移除', manual_parameters=[ openapi.Parameter('pk', openapi.IN_PATH, description='黑名单记录ID', type=openapi.TYPE_INTEGER), ], responses={200: success_response, 401: unauthorized_response, 404: not_found_response}, ) async def delete(self, request, pk): try: blacklist = await Blacklist.objects.aget(id=pk, user=request.user) except Blacklist.DoesNotExist: return create_standardized_error_response( code=ResponseCode.NOT_FOUND, message='黑名单记录不存在', status_code=status.HTTP_404_NOT_FOUND ) await blacklist.adelete() return create_standardized_response( data={'deleted': True}, code=ResponseCode.SUCCESS, status_code=status.HTTP_200_OK )