176 lines
6.3 KiB
Python
176 lines
6.3 KiB
Python
# Create your views here.
|
||
import os
|
||
from rest_framework.decorators import action
|
||
from rest_framework.response import Response
|
||
from rest_framework import status, viewsets, serializers
|
||
from rest_framework.permissions import IsAuthenticated
|
||
from crud_book.models import CrudBookModel, ReadingProgress
|
||
from crud_book.serializers import (
|
||
CrudBookModelSerializer,
|
||
CrudBookModelCreateUpdateSerializer,
|
||
ReadingProgressSerializer
|
||
)
|
||
from dvadmin.utils.viewset import CustomModelViewSet
|
||
|
||
|
||
class CrudBookModelViewSet(CustomModelViewSet):
|
||
"""
|
||
list:查询
|
||
create:新增
|
||
update:修改
|
||
retrieve:单例
|
||
destroy:删除
|
||
"""
|
||
queryset = CrudBookModel.objects.all()
|
||
serializer_class = CrudBookModelSerializer
|
||
create_serializer_class = CrudBookModelCreateUpdateSerializer
|
||
update_serializer_class = CrudBookModelCreateUpdateSerializer
|
||
|
||
@action(detail=True, methods=['get'])
|
||
def file(self, request, pk=None):
|
||
"""
|
||
获取图书文件信息或直接下载文件
|
||
"""
|
||
try:
|
||
# 先检查图书是否存在
|
||
try:
|
||
book = self.get_object()
|
||
except Exception as e:
|
||
return Response(
|
||
{'code': 404, 'msg': f'图书不存在: {str(e)}'},
|
||
status=status.HTTP_404_NOT_FOUND
|
||
)
|
||
|
||
# 检查图书是否有文件
|
||
if not book.file:
|
||
return Response(
|
||
{'code': 404, 'msg': '该图书没有上传文件'},
|
||
status=status.HTTP_404_NOT_FOUND
|
||
)
|
||
|
||
# 检查文件是否实际存在于文件系统
|
||
if not os.path.exists(book.file.path):
|
||
return Response(
|
||
{'code': 404, 'msg': '文件在服务器上不存在'},
|
||
status=status.HTTP_404_NOT_FOUND
|
||
)
|
||
|
||
# 返回文件URL信息作为标准格式
|
||
file_url = request.build_absolute_uri(book.file.url)
|
||
return Response({
|
||
'code': 2000,
|
||
'data': {
|
||
'file_url': file_url,
|
||
'file_type': book.file_type or 'epub',
|
||
'filename': os.path.basename(book.file.name)
|
||
},
|
||
'msg': '成功'
|
||
}, status=status.HTTP_200_OK)
|
||
|
||
except Exception as e:
|
||
return Response(
|
||
{'code': 500, 'msg': f'服务器错误: {str(e)}'},
|
||
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
||
)
|
||
|
||
|
||
class ReadingProgressViewSet(viewsets.ModelViewSet):
|
||
"""
|
||
阅读进度管理
|
||
"""
|
||
queryset = ReadingProgress.objects.all()
|
||
serializer_class = ReadingProgressSerializer
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def get_queryset(self):
|
||
"""只返回当前用户的阅读进度"""
|
||
return ReadingProgress.objects.filter(user=self.request.user)
|
||
|
||
def create(self, request, *args, **kwargs):
|
||
"""创建或更新阅读进度"""
|
||
# 检查用户是否已认证
|
||
if not request.user.is_authenticated:
|
||
return Response(
|
||
{'code': 401, 'msg': '用户未登录,无法保存阅读进度'},
|
||
status=status.HTTP_401_UNAUTHORIZED
|
||
)
|
||
|
||
# 获取序列化器
|
||
serializer = self.get_serializer(data=request.data)
|
||
|
||
try:
|
||
# 验证数据
|
||
serializer.is_valid(raise_exception=True)
|
||
|
||
# 尝试查找现有记录
|
||
try:
|
||
book_id = request.data.get('book_id')
|
||
book = CrudBookModel.objects.get(id=book_id)
|
||
|
||
# 使用update_or_create而不是普通的save,避免重复记录
|
||
progress, created = ReadingProgress.objects.get_or_create(
|
||
user=request.user,
|
||
book=book
|
||
)
|
||
|
||
# 更新字段
|
||
progress.location = request.data.get('location', '')
|
||
progress.progress = request.data.get('progress', 0)
|
||
progress.creator = request.user # 确保设置creator
|
||
progress.save()
|
||
|
||
# 返回更新后的序列化数据,包装成前端期望的格式
|
||
serializer = self.get_serializer(progress)
|
||
return Response(
|
||
{'code': 2000, 'data': serializer.data, 'msg': '成功'},
|
||
status=status.HTTP_200_OK
|
||
)
|
||
|
||
except CrudBookModel.DoesNotExist:
|
||
return Response(
|
||
{'code': 404, 'msg': f'ID为{book_id}的图书不存在'},
|
||
status=status.HTTP_404_NOT_FOUND
|
||
)
|
||
|
||
except serializers.ValidationError as e:
|
||
# 返回序列化验证错误
|
||
return Response(
|
||
{'code': 400, 'msg': str(e.detail)},
|
||
status=status.HTTP_400_BAD_REQUEST
|
||
)
|
||
except Exception as e:
|
||
# 记录错误
|
||
import logging
|
||
logger = logging.getLogger(__name__)
|
||
logger.error(f'保存阅读进度失败: {str(e)}')
|
||
|
||
return Response(
|
||
{'code': 500, 'msg': f'保存阅读进度失败: {str(e)}'},
|
||
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
||
)
|
||
|
||
@action(detail=False, methods=['get'])
|
||
def by_book(self, request):
|
||
"""根据图书ID获取阅读进度"""
|
||
book_id = request.query_params.get('book_id')
|
||
if not book_id:
|
||
return Response(
|
||
{'code': 400, 'msg': '缺少book_id参数'},
|
||
status=status.HTTP_400_BAD_REQUEST
|
||
)
|
||
|
||
try:
|
||
progress = ReadingProgress.objects.get(
|
||
user=request.user,
|
||
book_id=book_id
|
||
)
|
||
serializer = self.get_serializer(progress)
|
||
return Response(
|
||
{'code': 2000, 'data': serializer.data, 'msg': '成功'},
|
||
status=status.HTTP_200_OK
|
||
)
|
||
except ReadingProgress.DoesNotExist:
|
||
return Response(
|
||
{'code': 2000, 'data': {'location': '', 'progress': 0}, 'msg': '未找到阅读进度记录'},
|
||
status=status.HTTP_200_OK
|
||
) |