Python Django rest框架用户注册?

Python Django rest框架用户注册?,python,django,rest,serialization,django-rest-framework,Python,Django,Rest,Serialization,Django Rest Framework,我有以下问题,但面临无法解决的问题: 注册用户后,我无法与该用户一起登录api,因为密码没有散列 管理员中的“密码格式无效或哈希算法未知。” 当我未登录api时,我无法发布到“api/帐户”或在可浏览的api中查看表单 我的代码: from django.contrib.auth.models import User from rest_framework import serializers class UserSerializer(serializers.ModelSerializer):

我有以下问题,但面临无法解决的问题:

  • 注册用户后,我无法与该用户一起登录api,因为密码没有散列 管理员中的“密码格式无效或哈希算法未知。”
  • 当我未登录api时,我无法发布到“api/帐户”或在可浏览的api中查看表单
  • 我的代码:

    from django.contrib.auth.models import User
    from rest_framework import serializers
    
    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('password', 'first_name', 'last_name', 'email')
            write_only_fields = ('password',)
    
        def restore_object(self, attrs, instance=None):
            # call set_password on user object. Without this
            # the password will be stored in plain text.
            user = super(UserSerializer, self).restore_object(attrs, instance)
            user.set_password(attrs['password'])  #somehow not hashing
            return user
    

    请注意,set_password()不会保存对象,因为您已首先调用了super,所以您的对象已使用原始密码保存

    def post_save(self, obj, created=False):
        """
        On creation, replace the raw password with a hashed version.
        """
        if created:
            obj.set_password(obj.password)
            obj.save()
    
    只需使用post_save()保存密码即可

    def post_save(self, obj, created=False):
        """
        On creation, replace the raw password with a hashed version.
        """
        if created:
            obj.set_password(obj.password)
            obj.save()
    

    我在DRF3.0.2中尝试了公认的答案,但没有成功。密码没有被散列

    相反,在模型序列化程序中重写create方法

        def create(self, validated_data):
            user = User(email=validated_data['email'], username=validated_data['username'])
            user.set_password(validated_data['password'])
            user.save()
            return user
    

    这会在使用rest框架创建用户时散列密码,而不是post_save

    我们可以在用户中写入一个信号来解决此问题

    def create_hash(sender, instance=None, *args, **kwargs):
    passwd = instance.password
    instance.set_password(passwd)
    
    
    pre_save.connect(create_hash, sender=User)
    
    我已经使用了的解决方案来构建自己的解决方案。创建了一个空白的
    用户
    对象,以便我可以使用
    。set_password()


    与他的回答不同,我自己并不保存用户。我将此留给调用
    super
    的父类,这是DRF 3.X的另一种方法:

    from django.contrib.auth import get_user_model
    from django.contrib.auth.hashers import make_password
    
        def create(self, validated_data):    
            if validated_data.get('password'):
                validated_data['password'] = make_password(
                    validated_data['password']
                )
    
            user = get_user_model().objects.create(**validated_data)
    
            return user
    

    重写模型序列化器的创建

    def create(self, validated_data):
            if validated_data.get('password'):
                validated_data['password'] = make_password(validated_data['password'])
            return super(UserSerializer, self).create(validated_data)
    
    一定要进口

    from django.contrib.auth.hashers import make_password
    

    使用
    user.objects.create_user(**validated_data)
    创建用户(使用散列密码)可能比在DRF 3.0中使用两行更容易,在DRF 3.0中,
    write_only_fields=('password',)
    更改为
    extra_kwargs={'password':{'write_only':True},}
    另一个好的解决方案:你是完美的