lty/qy_lty/common/views.py
pmc bd95ba470c feat: update admin panel, API modules, and add migrations
- Update food, outfits, props, home-decor pages and components
- Add permissions page and sidebar updates
- Update API client and all API modules (auth, food, dances, etc.)
- Add card model migrations for optional fields
- Update Django views, serializers, and authentication
- Add affinity level migrations and user app updates
- Add project documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 13:06:50 +08:00

114 lines
4.3 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, parser_classes, authentication_classes, permission_classes
from rest_framework.response import Response
from rest_framework import status
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.permissions import IsAuthenticated
from django.views.decorators.csrf import csrf_exempt
from .oss import OSSUploader
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
import logging
import traceback
import os
from userapp.authentication import RedisTokenAuthentication
logger = logging.getLogger(__name__)
@swagger_auto_schema(
method='post',
operation_description="通用文件上传接口上传到OSS",
manual_parameters=[
openapi.Parameter(
'file',
openapi.IN_FORM,
description="需要上传的文件",
type=openapi.TYPE_FILE,
required=True
),
openapi.Parameter(
'is_permanent',
openapi.IN_FORM,
description="是否永久保存文件,默认为临时文件",
type=openapi.TYPE_BOOLEAN,
default=False
),
openapi.Parameter(
'filename',
openapi.IN_FORM,
description="自定义文件名(可选),如果不提供则自动生成",
type=openapi.TYPE_STRING,
required=False
),
],
responses={
200: openapi.Response(
description="上传成功",
schema=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'url': openapi.Schema(type=openapi.TYPE_STRING, description="文件访问URL"),
'key': openapi.Schema(type=openapi.TYPE_STRING, description="OSS对象键名"),
'is_permanent': openapi.Schema(type=openapi.TYPE_BOOLEAN, description="是否永久文件")
}
)
),
400: openapi.Response(description="请求错误或上传失败"),
401: openapi.Response(description="认证失败")
},
tags=['文件上传'],
security=[{'Bearer': []}]
)
@csrf_exempt
@api_view(['POST'])
@parser_classes([MultiPartParser, FormParser])
@authentication_classes([RedisTokenAuthentication])
@permission_classes([IsAuthenticated])
def upload_file(request):
"""
通用文件上传接口将文件上传到OSS
文件保存在 upload/{temporary|permanent}/{date}/{filename} 结构下
需要提供有效的认证令牌
"""
try:
# 检查是否有文件
if 'file' not in request.FILES:
print("[Upload] No file in request.FILES, keys:", list(request.FILES.keys()))
return Response({"error": "No file provided"}, status=status.HTTP_400_BAD_REQUEST)
file_obj = request.FILES['file']
original_name = file_obj.name
file_size = file_obj.size
content_type = getattr(file_obj, 'content_type', 'unknown')
print(f"[Upload] File received: {original_name}, size={file_size}, type={content_type}")
# 获取参数
is_permanent_raw = request.data.get('is_permanent', 'false')
is_permanent = str(is_permanent_raw).lower() == 'true'
filename = request.data.get('filename', None)
# 上传文件
uploader = OSSUploader()
result = uploader.upload_file(file_obj, is_permanent, filename)
# 返回包含前端需要的字段
_, ext = os.path.splitext(original_name)
response_data = {
'url': result['url'],
'key': result['key'],
'is_permanent': result['is_permanent'],
'filename': original_name,
'size': file_size,
'mimeType': content_type,
}
print(f"[Upload] Success: {result['url']}")
return Response(response_data, status=status.HTTP_200_OK)
except Exception as e:
error_detail = traceback.format_exc()
print(f"[Upload] ERROR: {error_detail}")
logger.error(f"File upload failed: {str(e)}\n{error_detail}")
return Response(
{"error": "File upload failed", "detail": str(e)},
status=status.HTTP_400_BAD_REQUEST
)