from django.db.models import Count from rest_framework import serializers from .models import Dish, DishCategory, Order class DishCategorySerializer(serializers.ModelSerializer): """分类序列化器""" dish_count = serializers.IntegerField(read_only=True) class Meta: model = DishCategory fields = ['id', 'name', 'icon', 'order', 'dish_count'] class DishSerializer(serializers.ModelSerializer): """菜品序列化器""" category_name = serializers.CharField(source='category.name', read_only=True) category_id = serializers.IntegerField(write_only=True, required=False, allow_null=True) class Meta: model = Dish fields = ['id', 'name', 'category', 'category_name', 'category_id', 'cover_image', 'description', 'ingredients', 'view_count', 'created_at', 'updated_at'] read_only_fields = ['created_at', 'updated_at', 'view_count'] class OrderSerializer(serializers.ModelSerializer): """订单序列化器""" dishes_detail = DishSerializer(source='dishes', many=True, read_only=True) ingredients_summary = serializers.SerializerMethodField() dish_ids = serializers.ListField( child=serializers.IntegerField(), write_only=True, required=False ) class Meta: model = Order fields = ['id', 'name', 'dishes', 'dishes_detail', 'dish_ids', 'status', 'party_date', 'participants', 'created_at', 'completed_at', 'note', 'ingredients_summary', 'images'] read_only_fields = ['created_at', 'completed_at'] extra_kwargs = { 'dishes': {'required': False} } def get_ingredients_summary(self, obj): # Compute in Python using prefetched dishes (avoids N+1) summary = {} for dish in obj.dishes.all(): for ing in dish.ingredients: name = ing.get('name', '').strip() amount = ing.get('amount', '').strip() if name: if name in summary: if amount: summary[name] += f" + {amount}" else: summary[name] = amount return [{'name': k, 'amount': v} for k, v in summary.items()] def create(self, validated_data): dish_ids = validated_data.pop('dish_ids', []) order = Order.objects.create(**validated_data) if dish_ids: dishes = Dish.objects.filter(id__in=dish_ids) order.dishes.set(dishes) return order def update(self, instance, validated_data): dish_ids = validated_data.pop('dish_ids', None) for attr, value in validated_data.items(): setattr(instance, attr, value) instance.save() if dish_ids is not None: dishes = Dish.objects.filter(id__in=dish_ids) instance.dishes.set(dishes) return instance