Files
chunyu_project/history/views.py
T

143 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.parsers import JSONParser
from adrf.views import APIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from asgiref.sync import sync_to_async
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
from adrf import generics
from adrf.generics import aget_object_or_404
from utils.response_codes import ResponseCode, create_standardized_response, create_standardized_error_response
from .models import BrowsingHistory
from .serializers import BrowsingHistorySerializer, BrowsingHistoryCreateSerializer
class HistoryPagination(PageNumberPagination):
page_size = 50
page_size_query_param = 'page_size'
max_page_size = 200
def get_paginated_response(self, data):
return Response({
'code': 10000,
'message': 'Success',
'data': {
'count': self.page.paginator.count,
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'results': data,
}
})
class BrowsingHistoryListCreateView(generics.ListCreateAPIView):
permission_classes = [IsAuthenticated]
parser_classes = [JSONParser]
pagination_class = HistoryPagination
def get_serializer_class(self):
if self.request.method == 'POST':
return BrowsingHistoryCreateSerializer
return BrowsingHistorySerializer
def get_queryset(self):
qs = BrowsingHistory.objects.filter(user=self.request.user)
# 隐藏实用工具、编程学习和文章资源
qs = qs.exclude(type__in=['utility', 'learn', 'article'])
record_type = self.request.query_params.get('type')
if record_type:
qs = qs.filter(type=record_type)
return qs
@swagger_auto_schema(
tags=['历史'],
operation_summary='获取浏览历史列表',
operation_description='获取当前用户的浏览历史记录,支持按类型筛选和分页',
manual_parameters=[
openapi.Parameter('type', openapi.IN_QUERY, description='记录类型筛选: tool/api', 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 list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
# 兜底:DRF 分页器内部同步评估 queryset(count + 切片取值)
page = await sync_to_async(self.paginate_queryset)(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
results = [x async for x in queryset]
serializer = self.get_serializer(results, many=True)
return Response({'code': 10000, 'message': 'Success', 'data': serializer.data})
@swagger_auto_schema(
tags=['历史'],
operation_summary='创建浏览记录',
operation_description='记录用户的浏览历史,同一链接一小时内重复访问会更新时间',
request_body=BrowsingHistoryCreateSerializer,
responses={201: success_response, 400: error_response, 401: unauthorized_response}
)
async def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
is_valid = await sync_to_async(serializer.is_valid)()
if is_valid:
# 兜底:serializer.create 内部有同步 ORM(filter/first/save/create)
instance = await sync_to_async(serializer.save)()
return create_standardized_response(
data=BrowsingHistorySerializer(instance).data,
code=ResponseCode.SUCCESS,
message='记录成功',
status_code=status.HTTP_201_CREATED
)
return create_standardized_error_response(
data=serializer.errors,
code=ResponseCode.VALIDATION_ERROR,
status_code=status.HTTP_400_BAD_REQUEST
)
class BrowsingHistoryDeleteView(APIView):
permission_classes = [IsAuthenticated]
@swagger_auto_schema(
tags=['历史'],
operation_summary='删除浏览记录',
operation_description='删除指定的浏览历史记录',
manual_parameters=[
openapi.Parameter('pk', openapi.IN_PATH, description='记录ID', type=openapi.TYPE_INTEGER, required=True),
],
responses={204: '删除成功', 401: unauthorized_response, 404: not_found_response}
)
async def delete(self, request, pk):
record = await aget_object_or_404(BrowsingHistory, pk=pk, user=request.user)
await record.adelete()
return create_standardized_response(
code=ResponseCode.SUCCESS,
message='删除成功',
status_code=status.HTTP_204_NO_CONTENT
)
class BrowsingHistoryClearView(APIView):
permission_classes = [IsAuthenticated]
@swagger_auto_schema(
tags=['历史'],
operation_summary='清空浏览记录',
operation_description='清空当前用户的所有浏览历史记录',
responses={200: success_response, 401: unauthorized_response}
)
async def delete(self, request):
count = (await BrowsingHistory.objects.filter(user=request.user).adelete())[0]
return create_standardized_response(
data={'deleted': count},
code=ResponseCode.SUCCESS,
message='清空成功'
)