我在django(AbstarctUser)中创建了自定义Userclass。一切正常,但即使在admin.py中注册后,我的密码也会以纯文本形式存储在数据库中。我没有任何明确定义的forms.py。
此外,我在tutorial之后使用嵌套序列化器。
我的代码如下
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)
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)
serializer = AddUserSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
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
答案 0 :(得分:1)
诀窍是使用user.set_password(password)
- >这在内部触发了密码散列机制:这是执行此操作的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()期间再次保存)
- 它没有处理序列化程序中的所有内容,部分工作正在与序列化程序和视图分开。
如果要将其全部保留在序列化程序中,可以执行以下操作:
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)
答案 1 :(得分: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()