0

我在 django(AbstarctUser) 中创建了自定义用户类。一切正常,但即使在 admin.py 中注册后,我的密码也会以纯文本形式存储在数据库中。我没有明确定义任何 forms.py。

此外,我在教程之后使用嵌套序列化程序。

我的代码如下

from django.contrib import admin
from .models import BasicUserInfo
from django.contrib.auth.admin import UserAdmin


class BasicUserAdmin(UserAdmin):
    pass

admin.site.register(BasicUserInfo, BasicUserAdmin)

编辑添加模型和视图

模型.py

class BasicUserInfo(AbstractUser):
    email = models.EmailField(primary_key=True, unique=True, db_index=True)

class UserInfo(models.Model):
    user = models.ForeignKey(BasicUserInfo, on_delete=models.CASCADE)

视图.py

serializer = AddUserSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
    serializer.create(validated_data=request.data)

序列化程序.py

class BasicUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = BasicUserInfo
        fields = ('username', 'password', 'email')

    print("hete")

    def create(self, validated_data):
        retval =  BasicUserInfo.objects.create(**validated_data)
        password = validated_data.pop('password')
        self.password = make_password(password)
       # self._password = password
        return retval

class AddUserSerializer(serializers.ModelSerializer):
    user = BasicUserSerializer(required=True)

    class Meta:
        model = UserInfo
        fields = ('phoneNo')

    def create(self, validated_data):
        user_data = validated_data.pop('user')
        user = BasicUserSerializer.create(BasicUserSerializer(), validated_data=user_data)
        user_info, created = UserInfo.objects.update_or_create(user=user, phoneNo=validated_data.pop('phoneNo'))
        return user_info
4

2 回答 2

1

诀窍是使用user.set_password(password)-> this 在内部触发密码散列机制:这是执行此操作的 Django 代码:

def set_password(self, raw_password):
    self.password = make_password(raw_password)
    self._password = raw_password

def make_password(password, salt=None, hasher='default'):
    """
    Turn a plain-text password into a hash for database storage

    Same as encode() but generate a new random salt. If password is None then
    return a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string,
    which disallows logins. Additional random string reduces chances of gaining
    access to staff or superuser accounts. See ticket #20079 for more info.
    """
    if password is None:
        return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
    hasher = get_hasher(hasher)
    salt = salt or hasher.salt()
    return hasher.encode(password, salt)

所以问题不serializers.create(**validated_data)在于执行make_password操作。上面的答案工作得很好,除了它做两件事不同 - 它保存用户两次(serailizer.create在`user.save()期间一次又一次) - 它没有处理序列化程序中的所有内容,部分工作正在拆分b /w 序列化程序和视图。

如果要将其全部保存在序列化程序中,可以执行以下操作:

class AddUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = BasicUserInfo

    def validate_password(self, value):
        return make_password(value)

更新:

我做了很多编辑;并试图解释原因。请耐心阅读,并在您认为合适的情况下进行更改。

class BasicUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = BasicUserInfo
        fields = ('username', 'password', 'email')

    def validate_password(self, value):
        return make_password(value)

class AddUserSerializer(serializers.ModelSerializer): 
    user = BasicUserSerializer(required=True) 
    class Meta: 
        model = UserInfo 
        fields = ('phoneNo') 

    def create(self, validated_data): 
        user_data = validated_data.pop('user') 
        user_serializer = BasicUserSerializer(data=user_data)
        if user_serializer.is_valid(raise_exception=True):
            user = user_serializer.save()
        validated_data['user'] = user
        return UserInfo.objects.create(**validated_data)
于 2018-05-23T18:48:00.460 回答
0

你不应该这样使用:

serializer = AddUserSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
    serializer.create(validated_data=request.data)

如果验证数据中有密码

最好这样使用:

password = request.data.pop('password', '')
if not password:
    raise ValidationError('password must not be empty')
serializer = AddUserSerializer(data=request.data)
serializer.is_valid(raise_exception=ValueError):
user = serializer.create(validated_data=request.data)
user.set_password(password)
user.save()
于 2018-05-23T18:28:22.050 回答