DRF-如果任何定义的字段为None

时间:2019-04-02 16:05:08

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

我需要将模型序列化为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之类的某些字段,因此当所需字段为UserSerializer时,我希望raise ValidationErrorNone

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

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

是否有一种方法可以validate序列化数据?请注意,我并不是在谈论deserialization

3 个答案:

答案 0 :(得分:1)

为什么验证无效?

仅当Deserialization过程 (输入是与对象类似的 dict )时,验证过程才经过 正在尝试 Serialization进程 。对于 Serialization ,DRF假定给定对象是有效对象,因此不需要验证。

来源DRF-serializers


我们如何做到这一点?

方法1
使您的用户对象成为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


方法2
覆盖 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

答案 1 :(得分:0)

您不需要。 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)

答案 2 :(得分:0)

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

您可以做的是,覆盖 to_representation ,如果必填字段值为None,则使该方法引发异常。

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

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