- 支持聚会创建后随时增减参与人员(进行中/已完成均可) - 美化参与次数排行榜界面,采用渐变进度条风格 - 新上传图片改用相对路径,避免端口变化导致图片无法加载 - 修复外网访问的 ALLOWED_HOSTS 配置 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
121 lines
4.2 KiB
Python
121 lines
4.2 KiB
Python
from pathlib import Path
|
|
from urllib.parse import urljoin
|
|
import uuid
|
|
|
|
from django.conf import settings
|
|
from django.core.files.storage import default_storage
|
|
from django.http import JsonResponse
|
|
from django.shortcuts import render
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from rest_framework import status, viewsets
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from menu.models import Dish, DishCategory, Order
|
|
from menu.serializers import DishSerializer, DishCategorySerializer, OrderSerializer
|
|
from menu.services import DishService, OrderService, ParserService
|
|
|
|
|
|
def index(request):
|
|
"""首页"""
|
|
return render(request, 'index.html')
|
|
|
|
|
|
@csrf_exempt
|
|
def upload_image(request):
|
|
"""上传图片"""
|
|
if request.method != 'POST':
|
|
return JsonResponse({'error': 'Method not allowed'}, status=405)
|
|
|
|
image = request.FILES.get('image')
|
|
if not image:
|
|
return JsonResponse({'error': 'No image provided'}, status=400)
|
|
|
|
ext = Path(image.name).suffix.lower()
|
|
if ext not in settings.ALLOWED_UPLOAD_IMAGE_EXTENSIONS:
|
|
return JsonResponse({'error': 'Unsupported image extension'}, status=400)
|
|
|
|
content_type = (image.content_type or '').lower()
|
|
if content_type not in settings.ALLOWED_UPLOAD_IMAGE_CONTENT_TYPES:
|
|
return JsonResponse({'error': 'Unsupported image content type'}, status=400)
|
|
|
|
if image.size > settings.MAX_UPLOAD_IMAGE_SIZE:
|
|
return JsonResponse({'error': 'Image file too large'}, status=400)
|
|
|
|
filename = f"dishes/{uuid.uuid4().hex}{ext}"
|
|
saved_path = default_storage.save(filename, image)
|
|
media_path = str(saved_path).lstrip('/')
|
|
media_url = urljoin(settings.MEDIA_URL, media_path)
|
|
|
|
return JsonResponse({'url': media_url})
|
|
|
|
|
|
class DishCategoryViewSet(viewsets.ModelViewSet):
|
|
"""分类视图"""
|
|
queryset = DishCategory.objects.all()
|
|
serializer_class = DishCategorySerializer
|
|
|
|
|
|
class DishViewSet(viewsets.ModelViewSet):
|
|
"""菜品视图"""
|
|
queryset = Dish.objects.all()
|
|
serializer_class = DishSerializer
|
|
|
|
def get_queryset(self):
|
|
category_id = self.request.query_params.get('category')
|
|
search = self.request.query_params.get('search')
|
|
return DishService.get_queryset(category_id, search)
|
|
|
|
def retrieve(self, request, *args, **kwargs):
|
|
instance = self.get_object()
|
|
DishService.increment_view_count(instance)
|
|
serializer = self.get_serializer(instance)
|
|
return Response(serializer.data)
|
|
|
|
|
|
class OrderViewSet(viewsets.ModelViewSet):
|
|
"""订单视图"""
|
|
queryset = Order.objects.all()
|
|
serializer_class = OrderSerializer
|
|
|
|
def get_queryset(self):
|
|
status_filter = self.request.query_params.get('status')
|
|
return OrderService.get_queryset(status_filter)
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
request_data = request.data.copy()
|
|
dish_ids = request_data.pop('dish_ids', [])
|
|
serializer = self.get_serializer(data=request_data)
|
|
serializer.is_valid(raise_exception=True)
|
|
order = OrderService.create_order(serializer, dish_ids)
|
|
response_serializer = self.get_serializer(order)
|
|
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def complete(self, request, pk=None):
|
|
order = self.get_object()
|
|
order = OrderService.complete_order(order)
|
|
serializer = self.get_serializer(order)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def share(self, request, pk=None):
|
|
order = self.get_object()
|
|
serializer = self.get_serializer(order)
|
|
return Response(serializer.data)
|
|
|
|
|
|
class ParseUrlView(APIView):
|
|
"""解析外部链接"""
|
|
|
|
def post(self, request):
|
|
url = request.data.get('url', '')
|
|
try:
|
|
result = ParserService.parse_url(url)
|
|
return Response(result)
|
|
except ValueError as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
except Exception as e:
|
|
return Response({'error': f'解析失败: {str(e)}'}, status=status.HTTP_400_BAD_REQUEST)
|