发布时出现 KeyError DRF

KeyError DRF when posting

当我 post 并且我不写电子邮件或电话时,我得到 KeyError。在我的代码中,需要电子邮件或电话,但不是两者都需要。 为什么会这样?

这是序列化器:

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = order
        fields = '__all__'
        extra_kwargs = {
            'email': {'required': False}, 'phonenumber': {'required': False}}

    def create(self, validated_data):
        order= Order.objects.create(
            email=validated_data['email'],
            phonenumber=validated_data['phonenumber'],
            food=validated_data['food']
        )
    

这是型号:

class Order(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    email = models.EmailField(max_length=200, unique=True)
    phonenumber = models.IntegerField(unique=True)
    food= models.ManyToManyField('Food', related_name='orders', blank=True)
    
    def __str__(self):
        return self.food

这是错误:

django-challenge-back | Traceback (most recent call last):
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
django-challenge-back |     response = get_response(request)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
django-challenge-back |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
django-challenge-back |     return view_func(*args, **kwargs)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
django-challenge-back |     return self.dispatch(request, *args, **kwargs)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
django-challenge-back |     response = self.handle_exception(exc)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
django-challenge-back |     self.raise_uncaught_exception(exc)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
django-challenge-back |     raise exc
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
django-challenge-back |     response = handler(request, *args, **kwargs)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/generics.py", line 190, in post
django-challenge-back |     return self.create(request, *args, **kwargs)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 19, in create
django-challenge-back |     self.perform_create(serializer)
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 24, in perform_create
django-challenge-back |     serializer.save()
django-challenge-back |   File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 205, in save
django-challenge-back |     self.instance = self.create(validated_data)
django-challenge-back |   File "/app/order/serializers.py", line 39, in create
django-challenge-back |     email=validated_data['email'],
django-challenge-back | KeyError: 'email'
django-challenge-back | [16/Apr/2021 20:02:22] "POST /pedido HTTP/1.1" 500 103807

原问题的答案:

如果 email 不在 validated_data 中,

email=validated_data['email'] 将抛出 KeyErrorphonenumber 也是如此。

您可以事先检查密钥是否存在或使用 .get 语法来避免错误,如果不存在则获取 None 值。

如果电子邮件不存在,

email=validated_data.get('email') 将 return None,而不是 KeyError.


为新方法编辑:

如果不需要,您需要允许空值(请参阅电子邮件和电话号码中添加的 null=True):

class Order(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    email = models.EmailField(max_length=200, unique=True, null=True)
    phonenumber = models.IntegerField(unique=True, null=True)
    food= models.ManyToManyField('Food', related_name='orders', blank=True)

现在不需要电子邮件或电话号码。如果你想让其中之一被要求添加一个 validate 方法到你的序列化程序来检查其中之一是否存在。

类似于:

class OrderSerializer(serializers.ModelSerializer):

    def validate(self, data):
        email = data.get('email')
        phonenumber = data.get('phonenumber')

        if not email and not phonenumber:
            raise serializers.ValidationError("one of email or phone number required")

        return data