如何在模型序列化器中改变字段的验证器

时间:2018-05-11 06:24:14

标签: django django-rest-framework

我使用ModelSerializer因为它会自动添加序列化字段。

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'last_login', 'email', 'is_admin', 'password_expiry', 'is_active', 'created_timestamp',
                  'modified_timestamp')

它生成如下的序列化器。

UserSerializer():
    id = IntegerField(label='ID', read_only=True)
    last_login = DateTimeField(allow_null=True, required=False)
    email = EmailField(label='Email address', max_length=255, validators=[<UniqueValidator(queryset=User.objects.all())>])
    is_admin = BooleanField(required=False)
    password_expiry = DateTimeField(allow_null=True, required=False)
    is_active = BooleanField(required=False)
    created_timestamp = DateTimeField(read_only=True)
    modified_timestamp = DateTimeField(read_only=True)

我们可以看到它会自动将UniqueValidator添加到email字段。 因此,如果我执行serializer.is_valid(),它将对所有字段执行字段类型验证,并为电子邮件字段执行UniqueValidator

这会导致问题。

我有一个API可以通过电子邮件ID查找用户列表。为简单起见,我使用现有的序列化程序动态创建自定义序列化程序。

CustomUserSerializer = UserSerializer
CustomUserSerialize.Meta.fields = ('email',)

现在,我期望执行的是仅验证电子邮件类型,而不验证UniqueValidator

请注意,我的源代码中没有单独的序列化程序。

1 个答案:

答案 0 :(得分:1)

您可以避免UniqueValidator ,方法是在序列化工具中将email字段指定为email = serializers.EmailField(),如下所示

class UserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField() # change is here <<<<
    class Meta:
        model = User
        fields = ('id', 'last_login', 'email', 'is_admin', 'password_expiry', 'is_active', 'created_timestamp',
                  'modified_timestamp')

更新1

然后我建议您为操作使用两个不同的序列化程序,一个用于GET,另一个用于creation。我假设您正在为ModelViewSet使用view类,因此,您可以覆盖get_serializer_class()方法以获得所需的结果。

serializer.py

class UserCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'last_login', 'email', 'is_admin', 'password_expiry', 'is_active', 'created_timestamp', 'modified_timestamp')


class UserGetSerializer(UserCreateSerializer):
    email = serializers.EmailField()

首选views.py

class UserAPIViewset(ModelViewSet):
    serializer_class = UserGetSerializer
    queryset = User.objects.all() 

    def get_serializer_class(self):
        if self.action == 'create':
            return UserCreateSerializer
        else:
            return UserGetSerializer  # other than "create"