所需密码Django REST API用户序列化器PUT请求

时间:2018-12-13 16:39:06

标签: django django-rest-framework

我是我的Django Rest API用户序列化程序中的一个问题:发出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 :(得分:3)

这不是串行器的问题。问题在于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)

答案 1 :(得分:1)

如果您正在使用 PUT 更新值,并且只想省略对password字段的验证,那么您可以尝试对viewset和{{3} }:

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