Some checks failed
Build and Deploy Backend / build-and-deploy (push) Failing after 1m36s
143 lines
4.5 KiB
Python
143 lines
4.5 KiB
Python
"""
|
||
故事模块视图 - App端
|
||
"""
|
||
from django.db.models import Count
|
||
from rest_framework import viewsets
|
||
from rest_framework.decorators import action
|
||
from rest_framework.permissions import IsAuthenticated
|
||
from drf_spectacular.utils import extend_schema
|
||
|
||
from utils.response import success, error
|
||
from utils.exceptions import ErrorCode
|
||
from apps.admins.authentication import AppJWTAuthentication
|
||
from .models import StoryShelf, Story
|
||
from .serializers import (
|
||
StoryShelfSerializer,
|
||
CreateShelfSerializer,
|
||
StoryListSerializer,
|
||
GenerateStorySerializer,
|
||
)
|
||
|
||
|
||
@extend_schema(tags=['故事'])
|
||
class StoryViewSet(viewsets.ViewSet):
|
||
"""故事视图集(App端)"""
|
||
|
||
authentication_classes = [AppJWTAuthentication]
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def list(self, request):
|
||
"""
|
||
获取故事列表
|
||
GET /api/v1/stories/?shelf_id=1&page=1&page_size=20
|
||
"""
|
||
queryset = Story.objects.filter(user=request.user)
|
||
|
||
shelf_id = request.query_params.get('shelf_id')
|
||
if shelf_id:
|
||
queryset = queryset.filter(shelf_id=shelf_id)
|
||
|
||
# 分页
|
||
page = int(request.query_params.get('page', 1))
|
||
page_size = int(request.query_params.get('page_size', 20))
|
||
start = (page - 1) * page_size
|
||
total = queryset.count()
|
||
items = queryset[start:start + page_size]
|
||
|
||
return success(data={
|
||
'total': total,
|
||
'items': StoryListSerializer(items, many=True).data,
|
||
})
|
||
|
||
def destroy(self, request, pk=None):
|
||
"""
|
||
删除故事
|
||
DELETE /api/v1/stories/{id}/
|
||
"""
|
||
try:
|
||
story = Story.objects.get(id=pk, user=request.user)
|
||
except Story.DoesNotExist:
|
||
return error(code=ErrorCode.STORY_NOT_FOUND, message='故事不存在')
|
||
story.delete()
|
||
return success(message='删除成功')
|
||
|
||
@action(detail=False, methods=['post'], url_path='generate')
|
||
def generate(self, request):
|
||
"""
|
||
生成故事 (SSE 流式 - 占位)
|
||
POST /api/v1/stories/generate/
|
||
"""
|
||
serializer = GenerateStorySerializer(data=request.data)
|
||
if not serializer.is_valid():
|
||
return error(message=str(serializer.errors))
|
||
|
||
# TODO: 接入 LLM API 实现 SSE 流式生成
|
||
shelf_id = serializer.validated_data.get('shelf_id')
|
||
shelf = None
|
||
if shelf_id:
|
||
try:
|
||
shelf = StoryShelf.objects.get(id=shelf_id, user=request.user)
|
||
except StoryShelf.DoesNotExist:
|
||
return error(code=ErrorCode.SHELF_NOT_FOUND, message='书架不存在')
|
||
|
||
story = Story.objects.create(
|
||
user=request.user,
|
||
shelf=shelf,
|
||
title='生成中...',
|
||
content='',
|
||
generation_mode=serializer.validated_data.get('mode', 'random'),
|
||
prompt=serializer.validated_data.get('prompt', ''),
|
||
)
|
||
|
||
return success(data={
|
||
'id': story.id,
|
||
'message': '故事生成功能待接入 LLM API',
|
||
})
|
||
|
||
|
||
@extend_schema(tags=['故事'])
|
||
class ShelfViewSet(viewsets.ViewSet):
|
||
"""书架视图集(App端)"""
|
||
|
||
authentication_classes = [AppJWTAuthentication]
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def list(self, request):
|
||
"""
|
||
书架列表
|
||
GET /api/v1/stories/shelves/
|
||
"""
|
||
shelves = StoryShelf.objects.filter(
|
||
user=request.user
|
||
).annotate(story_count=Count('stories'))
|
||
return success(data=StoryShelfSerializer(shelves, many=True).data)
|
||
|
||
def create(self, request):
|
||
"""
|
||
创建书架
|
||
POST /api/v1/stories/shelves/
|
||
"""
|
||
serializer = CreateShelfSerializer(data=request.data)
|
||
if not serializer.is_valid():
|
||
return error(message=str(serializer.errors))
|
||
|
||
shelf = StoryShelf.objects.create(
|
||
user=request.user,
|
||
name=serializer.validated_data['name'],
|
||
)
|
||
return success(data=StoryShelfSerializer(shelf).data, message='创建成功')
|
||
|
||
def destroy(self, request, pk=None):
|
||
"""
|
||
删除书架(故事保留,shelf_id 置 null)
|
||
DELETE /api/v1/stories/shelves/{id}/
|
||
"""
|
||
try:
|
||
shelf = StoryShelf.objects.get(id=pk, user=request.user)
|
||
except StoryShelf.DoesNotExist:
|
||
return error(code=ErrorCode.SHELF_NOT_FOUND, message='书架不存在')
|
||
|
||
Story.objects.filter(shelf=shelf).update(shelf=None)
|
||
shelf.delete()
|
||
return success(message='删除成功')
|