2026-03-12 11:27:23 +08:00
|
|
|
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):
|
2026-03-23 17:18:59 +08:00
|
|
|
# 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()]
|
2026-03-12 11:27:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|