django 如何在序列化器上发送多个对象,序列化器(得到了non_field_errors)

but5z9lq  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(144)

我试图通过create viewset方法向序列化程序发送多个数据。但是,当这样做时,我得到一个错误如下:
Error message
我在序列化器中使用了很多属性,但我还是会得到同样的错误。我发布的数据是这样的:

[
  {
    "weekday":"day",
    "start_time":"time",
    "end_time":"time"  
  },
  {
    "weekday":"day",
    "start_time":"time",
    "end_time":"time"  
  }
]

这是视图集和序列化器代码:

viewset.py

class SpecialistAvailabilityView(viewsets.ModelViewSet):

    model = SpecialistAvailability
    permission_classes = [IsAuthenticated, IsSpecialist]
    
    def get_serializer_class(self):
        saving_actions = ["create", "update", "partial_update"]
        if self.action in saving_actions:
            return WeekDayTimeSerializer
        
        return SpecialistAvailabilitySerializer

    def get_queryset(self):
        queryset = SpecialistAvailability.objects.filter(
            specialist__user=self.request.user
        ).order_by('-start_time__week_day')
        return queryset
    
    def translate_availability(self, data):
        pass

    def create(self, request, *args, **kwargs):
        serializer = WeekDayTimeSerializer(data=request.data, many=isinstance(request.data, list))
        print(serializer.initial_data)
        print(serializer.is_valid())
        if serializer.is_valid():
            self.translate_availability(serializer.validated_data)
        return super().create(request, *args, **kwargs)

serializer.py

import pytz

from datetime import datetime

from rest_framework import serializers

from apps.specialist.models.specialist_availability import SpecialistAvailability
from apps.specialist.utils import WEEKDAYS

class WeekDayTimeSerializer(serializers.Serializer):
    weekday = serializers.ChoiceField(choices=WEEKDAYS, required=True)
    start_time = serializers.TimeField()
    end_time = serializers.TimeField()

    # TODO ADD TIME AND WEEKDAY CHECKING
    # START TIME MUST BE LESS THAN END TIME
    # JUST ONE DAY MUST BE SENDED IF MANY

    def validate(self, attrs):
        self.validate_start_time(attrs['start_time'])
        self.validate_start_time(attrs['end_time'])
        self.validate_end_time
        return super().validate(attrs)
    
    def validate_start_time(self, start_time):
        try:
            datetime.strptime(start_time, "%H:%M")
        except:
            raise serializers.ValidationError("Wrong time format")
        
        return start_time
    
    def validate_end_time(self, end_time):
        try:
            datetime.strptime(end_time, "%H:%M")
        except:
            raise serializers.ValidationError("Wrong time format")
        
        return end_time

class SpecialistAvailabilitySerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecialistAvailability
        fields = ['id', 'specialist', 'start_time', 'end_time']

    def to_representation(self, instance):
        localized_start_time = self.set_time_to_local(instance.start_time)
        localized_end_time = self.set_time_to_local(instance.end_time)
        data = {
            'availability': {
                'id': instance.id,
                'start_day': localized_start_time.strftime('%A'),
                'start_day_code': localized_start_time.isoweekday(),
                'start_time': localized_start_time.time(),
                'end_day': localized_end_time.strftime('%A'),
                'end_day_code': localized_end_time.isoweekday(),
                'end_time': localized_end_time.time()
            }
        }
        return data

    def validate(self, attrs):
        instance = getattr(self, 'instance', None)
        if instance:
            attrs['id'] = instance.id

        specialist_availability = self.Meta.model(**attrs)
        specialist_availability.clean()
        super().validate(attrs)
        attrs['start_time'] = self.set_time_to_utc(attrs['start_time'])
        attrs['end_time'] = self.set_time_to_utc(attrs['end_time'])
        return attrs
    
    def set_time_to_local(self, time):
        request_user = self.context['request'].user
        user_tz = request_user.timezone
        if user_tz == pytz.utc:
            return time
        
        unlocalized_time = time.replace(tzinfo=None)
        utc_time = pytz.utc.localize(unlocalized_time)
        local_time = utc_time.astimezone(user_tz)
        return local_time

    def set_time_to_utc(self, time):
        request_user = self.context['request'].user
        user_tz = request_user.timezone
        if user_tz == pytz.utc:
            return time
        
        unlocalized_time = time.replace(tzinfo=None)
        local_time = user_tz.localize(unlocalized_time)
        utc_time = local_time.astimezone(pytz.utc)
        return utc_time
v440hwme

v440hwme1#

您已经在SpecialistAvailabilityView,中覆盖了viewsets.ModelViewSet的方法create(),但毕竟您只是调用父方法super().create(request, *args, **kwargs)。因此,实际上,你自己的代码在方法create()中并不适用。
同时,父create()方法总是在序列化器调用中使用many=False
所以,你只需要替换行

return super().create(request, *args, **kwargs)

return Response(serializer.data, status=status.HTTP_201_CREATED)

相关问题