from rest_framework import serializers from .models import City, Attraction from django.contrib.auth import get_user_model from django.conf import settings from .models import RedTourismPlan, RedTourismDayPlan, RedTourismSpot User = get_user_model() class CitySerializer(serializers.ModelSerializer): class Meta: model = City fields = ['id', 'name', 'code', 'image', 'description', 'latitude', 'longitude'] class AttractionSerializer(serializers.ModelSerializer): city = CitySerializer(read_only=True) tags = serializers.SerializerMethodField() image_url = serializers.SerializerMethodField() class Meta: model = Attraction fields = ['id', 'city', 'name', 'description', 'short_desc', 'address', 'ticket_price', 'open_hours', 'image_url', 'tags', 'is_featured', 'latitude', 'longitude'] def get_tags(self, obj): if isinstance(obj.tags, str): return [tag.strip() for tag in obj.tags.split(',')] return obj.tags or [] def get_image_url(self, obj): # 确保使用正确的媒体URL if obj.image: return self.context['request'].build_absolute_uri(obj.image.url) return f"{settings.MEDIA_URL}attractions/{obj.name}.png" # class RedTourismPlanSerializer(serializers.Serializer): # plan_id = serializers.IntegerField(required=False, allow_null=True) # city_ids = serializers.ListField( # child=serializers.IntegerField(), # required=True # ) # days = serializers.IntegerField(min_value=1, max_value=7, required=True) # interests = serializers.ListField( # child=serializers.CharField(), # required=True # ) # transport = serializers.CharField(required=True) # custom_requirements = serializers.CharField(required=False, allow_blank=True) # previous_plan = serializers.DictField(required=False, default=dict) # cities = CitySerializer(many=True, read_only=True) class RedTourismSpotSerializer(serializers.ModelSerializer): class Meta: model = RedTourismSpot fields = '__all__' class RedTourismDayPlanSerializer(serializers.ModelSerializer): spots = RedTourismSpotSerializer(many=True, read_only=True) class Meta: model = RedTourismDayPlan fields = '__all__' class RedTourismPlanSerializer(serializers.ModelSerializer): day_plans = RedTourismDayPlanSerializer(many=True, read_only=True) cities = CitySerializer(many=True, read_only=True) created_at = serializers.DateTimeField(format="%Y-%m-%d") # 格式化日期 class Meta: model = RedTourismPlan fields = '__all__' read_only_fields = ('user', 'created_at', 'last_updated') # serializers.py class SaveRedTourismPlanSerializer(serializers.Serializer): plan_data = serializers.JSONField() city_ids = serializers.ListField( child=serializers.IntegerField(), required=True ) def validate_plan_data(self, value): required_fields = ['title', 'description', 'days', 'statistics'] for field in required_fields: if field not in value: raise serializers.ValidationError(f"缺少必要字段: {field}") return value def validate_city_ids(self, value): if not value: raise serializers.ValidationError("至少需要一个城市ID") return value # serializers.py from rest_framework import serializers class RedTourismRegenerateSerializer(serializers.Serializer): plan_id = serializers.IntegerField(required=False, allow_null=True) city_ids = serializers.ListField( child=serializers.IntegerField(), required=True ) days = serializers.IntegerField(min_value=1, max_value=7, required=True) interests = serializers.ListField( child=serializers.CharField(), required=True ) transport = serializers.ChoiceField( choices=['public', 'drive', 'walk', 'bike'], required=True ) custom_requirements = serializers.CharField(required=False, allow_blank=True) previous_plan = serializers.DictField(required=True) def validate_previous_plan(self, value): """验证previous_plan字段的结构""" if not isinstance(value, dict): raise serializers.ValidationError("previous_plan必须是字典") # 确保有days字段 if 'days' not in value: raise serializers.ValidationError("previous_plan必须包含days字段") if not isinstance(value['days'], list): raise serializers.ValidationError("previous_plan.days必须是列表") return value