Как мутировать валидаторы полей в сериализаторе моделей - PullRequest
0 голосов
/ 11 мая 2018

Я использую 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 для поиска списка пользователей по идентификатору электронной почты.Для простоты я использовал существующий сериализатор для динамического создания собственного сериализатора.

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

Теперь, что я ожидаю выполнить, это проверить только тип электронной почты, но не UniqueValidator.

Обратите вниманиечто я не хочу иметь отдельный сериализатор для этого в моем исходном коде.

1 Ответ

0 голосов
/ 11 мая 2018

Вы можете избежать 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" 
...