Требуется пароль DJango REST API Пользовательский сериализатор PUT-запрос - PullRequest
0 голосов
/ 13 декабря 2018

Проблема в том, что в моем Django Rest API User Serializer: поле пароля необходимо при выполнении запроса PUT.В запросе POST это имеет смысл, но с PUT особенно, если PUT выполняется администратором, поле пароля должно быть пустым.

Как я могу изменить свой сериализатор так, чтобы пароль был необходим для POST, но пусто для PUT?

class UserSerializer(serializers.ModelSerializer):
    """The UserSerializer"""
    gender = serializers.IntegerField(source='profile.gender', read_only=False)
    clinic = serializers.CharField(
        source='profile.clinic.code', read_only=False)
    title_prefix = serializers.CharField(
        source='profile.academic_title_prefix',
        allow_blank=True,
        read_only=False)
    title_suffix = serializers.CharField(
        source='profile.academic_title_suffix',
        allow_blank=True,
        read_only=False)

    email = serializers.EmailField(
        required=True,
        validators=[UniqueValidator(queryset=User.objects.all())])
    username = serializers.CharField(
        validators=[UniqueValidator(queryset=User.objects.all())])
    password = serializers.CharField(min_length=8, write_only=True)

    class Meta:
        model = User
        fields = ('id', 'url', 'username', 'first_name', 'last_name', 'gender',
                  'title_prefix', 'title_suffix', 'clinic', 'email',
                  'is_staff', 'is_superuser', 'date_joined', 'last_login',
                  'password')


    def create(self, validated_data):
        """Create and return a new user and its associated profile."""

        user = User.objects.create_user(
            validated_data['username'],
            validated_data['email'],
            validated_data['password'],
        )

        user.set_password(validated_data['password'])

        user.first_name = validated_data['first_name']
        user.last_name = validated_data['last_name']
        user.is_staff = validated_data['is_staff']
        user.is_superuser = validated_data['is_superuser']

        user.save()

        # create associated profile
        profile_data = validated_data.pop('profile')

        profile = Profile.objects.create(
            user=user,
            gender=profile_data['gender'],
            clinic=Clinic.objects.get(code=profile_data['clinic']['code']),
            academic_title_prefix=profile_data['academic_title_prefix'],
            academic_title_suffix=profile_data['academic_title_suffix'],
        )
        user.profile = profile

        return user

    def update(self, instance, validated_data):
        """Update and return a existing user and its associated profile."""

        instance.first_name = validated_data.get('first_name',
                                                 instance.first_name)
        instance.last_name = validated_data.get('last_name',
                                                instance.last_name)

        # Only Superuser can make Superusers
        if self.context['request'].user.is_superuser:
            instance.is_staff = validated_data.get('is_staff',
                                                   instance.is_staff)
            instance.is_superuser = validated_data.get('is_superuser',
                                                       instance.is_superuser)

        profile_data = validated_data.pop('profile')

        profile = Profile.objects.get(user=instance)
        profile.gender = profile_data['gender']
        profile.clinic = Clinic.objects.get(
            code=profile_data['clinic']['code'])
        profile.academic_title_prefix = profile_data['academic_title_prefix']
        profile.academic_title_suffix = profile_data['academic_title_suffix']
        profile.save()
        instance.profile = profile

        return instance

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Если вы используете PUT для обновления значений и хотите пропустить проверку только для поля password, то вы можете попробовать вот так для viewset и универсальных представлений:

class UserSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super(UserSerializer, self).__init__(*args, **kwargs)
        if self.context['request'].method == "PUT":
            self.fields.pop('password')

   # rest of the code
0 голосов
/ 13 декабря 2018

Это не проблема сериализатора.Проблема в том, что DRF требует все поля, используя метод PUT .Метод, для которого не требуются все поля: PATCH .

Вам необходимо переопределить метод обновления в наборе:

def update(self, request, *args, **kwargs):
    partial = True # Here I change partial to True
    instance = self.get_object()
    serializer = self.get_serializer(instance, data=request.data, partial=partial)
    serializer.is_valid(raise_exception=True)
    self.perform_update(serializer)

    return Response(serializer.data)
...