【问题标题】:DRF - Raise Exception if any defined field is NoneDRF - 如果任何定义的字段为无,则引发异常
【发布时间】:2019-08-24 00:53:47
【问题描述】:

我需要将模型序列化为JSON。然后将此JSON 发送给一个API

但是这个API 要求某些字段不是None

我有这些字段的列表。在这种情况下,假设它只是['telephone'],但它可以更多。

例如:

class UserSerializer(serializers.ModelSerializer):
    telephone = serializers.CharField(source='userprofile.telephone')
    class Meta:
        model = User
        fields = ['first_name','last_name','telephone']

序列化:

>>> UserSerializer(user).data
>>> {'first_name':'Michael','last_name':'Jackson','telephone':None}

由于API 需要telephone 等一些字段,所以当必填字段为None 时,我希望UserSerializerraise ValidationError

所以在这种情况下我无法序列化user,因为telephoneNone

我尝试了很多方法,包括将required=True 添加到telephone,但没有任何效果。

有没有办法validate序列化数据?请注意,我说的不是deserialization

【问题讨论】:

  • 为什么你尝试使用required=False 而不是required=True
  • 输入错误。当然我试过 required=True :)

标签: python django django-models django-rest-framework


【解决方案1】:

你不需要。 DRF 序列化程序开箱即用。如果某个字段设置为null=Falserequired=True,则执行此操作。

data = UserSerializer(data=user_data)
data.is_valid(raise_exception=True

就是这样。将引发 400 错误。

如果你愿意,你可以调整错误信息:

data = UserSerializer(data=user_data)
try:
    data.is_valid(raise_exception=True)
except ValidationError as e:
   return HttpResponse(status_code=400, content=e)

【讨论】:

  • 谢谢,但user_data 是什么。我想序列化模型。
  • 此外,我不能将 required=True 用于任何只读字段,例如SerializerMethodField
  • 所以你需要使用serializers.ModelSerializer,而不是MethodSerializer
  • user_data 只是任何通用字典,其中包含您将用于创建模型实例的信息。
【解决方案2】:

您想要的不是验证反序列化的数据,而是验证序列化。 required=True 等表达式都用于验证数据以进行反序列化。序列化在 Serializer 类的 to_representation 方法中处理(这是 ModelSerializer 的基础)

您可以做的是,覆盖 to_representation,并让该方法在必填字段值为 None 时引发异常。

您可能需要进一步继承默认的 DRF 类,例如 Field(用于序列化器字段),并使用您的自定义类来系统地提供您的功能。您不想为此依赖 required=True,因为它已经用于其他目的(用于反序列化验证)。

我的建议是,子类 Field 类,添加一个类似“required_for_read”的属性,并使用您的自定义字段类使用此属性定义您的序列化器字段。然后,在您重写的 to_representation 方法中,查找该属性,如果该字段的该属性为 True 但其值为 None,则引发异常>

【讨论】:

    【解决方案3】:

    为什么验证不起作用?

    验证过程仅在Deserialization 过程(输入是dict 类对象)并且您正在尝试Serialization 进程。对于 Serialization,DRF 假定给定对象是有效对象,因此不需要验证。

    来源DRF-serializers


    我们怎样才能做到这一点?

    方法一
    将您的用户对象设置为 user_data(dict 对象)并将其传递给序列化程序并运行验证。

    user = User.objects.get(id=1)
    dict_user_data = {"first_name": user.first_name, "last_name": user.last_name, "telephone": user.userprofile.telephone}
    user_serializer = UserSerializer(data=dict_user_data)
    user_serializer.is_valid(True)
    user_serializer.data


    方法二
    覆盖 to_representation() 方法

    class UserSerializer(serializers.ModelSerializer):
        telephone = serializers.CharField(source='userprofile.telephone')
    
        class Meta:
            model = User
            fields = ['first_name', 'last_name', 'telephone']
    
        def to_representation(self, instance):
            data = super().to_representation(instance)
            for field, value in data.items():
                if value is None:
                    raise SomeExceptionHere({field: "can't be None"})
            return data

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多