Files
game-cards-poker-design/backend/apps/projects/views.py
2026-06-03 22:13:13 +08:00

179 lines
6.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.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.core.files.storage import default_storage
from django.conf import settings
from PIL import Image
import os
from .models import Project, Asset
from .serializers import ProjectSerializer, ProjectDetailSerializer, AssetSerializer
@api_view(['GET', 'POST'])
def project_list(request):
"""获取项目列表或创建新项目"""
if request.method == 'GET':
projects = Project.objects.all()
serializer = ProjectSerializer(projects, many=True)
return Response(serializer.data)
elif request.method == 'POST':
# 自动补默认 design/card_overrides/number_layout
data = dict(request.data or {})
if 'design' not in data:
data['design'] = Project._meta.get_field('design').default()
if 'card_overrides' not in data:
data['card_overrides'] = Project._meta.get_field('card_overrides').default()
if 'number_layout' not in data:
data['number_layout'] = Project._meta.get_field('number_layout').default()
if 'back_design' not in data:
data['back_design'] = Project._meta.get_field('back_design').default()
# 抽出 template_id不写进 Project 字段)
template_id = data.pop('template_id', None)
serializer = ProjectSerializer(data=data)
if serializer.is_valid():
project = serializer.save()
# 如果传了 template_id自动套用模板预设
template_apply_result = None
if template_id:
from apps.templates.models import CardTemplate
from apps.templates.template_apply import apply_template_to_project
try:
tpl = CardTemplate.objects.get(pk=template_id)
template_apply_result = apply_template_to_project(project, tpl)
except CardTemplate.DoesNotExist:
template_apply_result = {'error': f'template {template_id} not found'}
# 重新读一次apply_template 已修改了 design 和 assets
project.refresh_from_db()
return Response({
**ProjectSerializer(project).data,
'template_apply': template_apply_result,
}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def project_detail(request, pk):
"""获取、更新或删除项目"""
try:
project = Project.objects.get(pk=pk)
except Project.DoesNotExist:
return Response({'error': 'Project not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = ProjectDetailSerializer(project)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = ProjectSerializer(project, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
project.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['POST'])
def project_save_design(request, pk):
"""整体保存项目设计design / card_overrides / number_layout"""
try:
project = Project.objects.get(pk=pk)
except Project.DoesNotExist:
return Response({'error': 'Project not found'}, status=status.HTTP_404_NOT_FOUND)
for field in ('design', 'back_design', 'card_overrides', 'number_layout', 'face_orientations'):
if field in request.data:
setattr(project, field, request.data[field])
project.save()
return Response({
'ok': True,
'design': project.design,
'back_design': project.back_design,
'card_overrides': project.card_overrides,
'number_layout': project.number_layout,
'face_orientations': project.face_orientations,
})
@api_view(['GET', 'POST'])
def asset_list(request, project_pk):
"""获取项目素材列表或上传新素材"""
try:
project = Project.objects.get(pk=project_pk)
except Project.DoesNotExist:
return Response({'error': 'Project not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
assets = project.assets.all()
serializer = AssetSerializer(assets, many=True, context={'request': request})
return Response(serializer.data)
elif request.method == 'POST':
if 'file' not in request.FILES:
return Response({'error': 'No file provided'}, status=status.HTTP_400_BAD_REQUEST)
file = request.FILES['file']
asset_type = request.POST.get('asset_type', 'unknown')
asset_key = request.POST.get('asset_key', 'unknown')
# 创建项目素材目录
project_media_dir = os.path.join('projects', str(project.id), asset_type)
full_dir = os.path.join(settings.MEDIA_ROOT, project_media_dir)
os.makedirs(full_dir, exist_ok=True)
# 避免重名覆盖:补上时间戳
from time import time
ts = int(time() * 1000)
file_name = f"{asset_key}_{ts}_{file.name}"
file_path = os.path.join(project_media_dir, file_name)
saved_path = default_storage.save(file_path, file)
# 获取图片尺寸
width, height = None, None
try:
img = Image.open(file)
width, height = img.size
except Exception:
pass
asset = Asset.objects.create(
project=project,
asset_type=asset_type,
asset_key=asset_key,
file_path=saved_path,
file_name=file_name,
width=width,
height=height,
)
serializer = AssetSerializer(asset, context={'request': request})
return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(['GET', 'DELETE'])
def asset_detail(request, project_pk, asset_pk):
"""获取或删除单个素材"""
try:
project = Project.objects.get(pk=project_pk)
asset = project.assets.get(pk=asset_pk)
except (Project.DoesNotExist, Asset.DoesNotExist):
return Response({'error': 'Asset not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = AssetSerializer(asset, context={'request': request})
return Response(serializer.data)
elif request.method == 'DELETE':
if asset.file_path:
file_full_path = os.path.join(settings.MEDIA_ROOT, asset.file_path)
if os.path.exists(file_full_path):
try:
os.remove(file_full_path)
except OSError:
pass
asset.delete()
return Response(status=status.HTTP_204_NO_CONTENT)