Django Rest Framework:更新

时间:2016-01-11 09:25:41

标签: python django serialization passwords django-rest-framework

我正在尝试使用Django Rest Framework(通过PUT调用)更新自定义用户模型,虽然我可以正常更新模型的用户名和密码,但密码不会这样做:当我检查用户的时候密码通过django admin我得到“无效的密码格式或未知的散列算法。”

以下是我的views.py和serializers.py的相关部分:

class AccountViewSet(viewsets.ModelViewSet):
lookup_field = 'username'
queryset = Account.objects.all()
serializer_class = AccountSerializer

def get_permissions(self):
    if self.request.method in permissions.SAFE_METHODS:
        return (permissions.IsAdminUser(),)

    if self.request.method == 'POST':
        return (permissions.AllowAny(),)

    return (permissions.IsAdminUser(),)

def create(self, request):
    serializer = self.serializer_class(data=request.data)

    if serializer.is_valid(raise_exception=True):
        Account.objects.create_user(**serializer.validated_data)

        return Response(serializer.validated_data, status = status.HTTP_201_CREATED)

    return Response({
        'status': 'Bad request',
        'message': 'Account could not be created with received data.'
    }, status = status.HTTP_400_BAD_REQUEST)

_

class AccountSerializer(serializers.HyperlinkedModelSerializer):

password = serializers.CharField(write_only = True, required = False)
confirm_password = serializers.CharField(write_only = True, required = False)

def validate(self, data):
    if data.get('password') != data.get('confirm_password'):
        raise serializers.ValidationError("Passwords do not match.")
    else:
        temp = Account(email = data.get('email'), username = data.get('username'))
        validate_password(data.get('password'), temp)
    return data

class Meta:

    model = Account

    fields = (
        'id',
        'email',
        'username',
        'created_at',
        'updated_at',
        'password',
        'confirm_password'
    )
    read_only_fields = (
        'created_at',
        'updated_at'
    )

    def create(self, validated_data):
        return Account.objects.create(**validated_data)

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            if attr == 'password':
                instance.set_password(value)
            else:
                setattr(instance, attr, value)

        instance.save()

        update_session_auth_hash(self.context.get('request'), instance)

        return instance

现在,我的理解是我不应该覆盖AccountViewSet的update()(由超类ModelViewSet提供),因为它应该自动调用序列化程序的save(),而后者应该调用序列化程序的更新( )。由于它不起作用,我也尝试在AccountViewSet中实现我自己的update(),其方式与相应的create()方法被覆盖相同,但这似乎也不起作用。事实上,在这两种情况下,我甚至无法验证序列化程序的update()是否被调用,这使我认为我的序列化程序的update()方法没有被调用,而是调用了它的超类'update(),会解释密码没有被散列。显然我做错了,只要调用我自己的序列化程序的update()方法,但是我无法弄清楚什么,也找不到任何其他能够真正解决这个问题的答案。

1 个答案:

答案 0 :(得分:1)

我不知道您的代码问题,但请从https://thinkster.io/django-angularjs-tutorial

尝试此序列化程序
class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)
    confirm_password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = Account
        fields = ('id', 'email', 'username', 'created_at', 'updated_at',
                  'first_name', 'last_name', 'tagline', 'password',
                  'confirm_password',)
        read_only_fields = ('created_at', 'updated_at',)

        def create(self, validated_data):
            return Account.objects.create(**validated_data)

        def update(self, instance, validated_data):
            instance.username = validated_data.get('username', instance.username)
            instance.tagline = validated_data.get('tagline', instance.tagline)

            instance.save()

            password = validated_data.get('password', None)
            confirm_password = validated_data.get('confirm_password', None)

            if password and confirm_password and password == confirm_password:
                instance.set_password(password)
                instance.save()

            update_session_auth_hash(self.context.get('request'), instance)

            return instance