Django自定义用户模型登录失败:密码格式无效或哈希算法未知
解决Django自定义用户模型创建后密码无效的问题
1. 修复自定义UserManager的密码处理逻辑
Django要求用户密码必须经过哈希存储,直接赋值user.password = password会导致明文存储,触发"Invalid password format"错误。必须使用set_password()方法自动处理密码哈希。
正确的UserManager示例:
from django.contrib.auth.models import BaseUserManager class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('The Email field must be set') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) # 关键:用set_password处理密码哈希 user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self.create_user(email, password, **extra_fields)
2. 确保自定义User模型配置正确
User模型必须继承AbstractBaseUser和PermissionsMixin,并指定自定义的UserManager:
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.db import models class CustomUser(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) name = models.CharField(max_length=255) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['name'] objects = CustomUserManager() def __str__(self): return self.email
3. 修改CreateView的用户创建逻辑
默认CreateView会直接调用表单的save()创建模型实例,不会触发UserManager的create_user方法,导致密码未哈希。可以通过两种方式修复:
方法一:自定义ModelForm,重写save方法
from django import forms from .models import CustomUser class CustomUserCreationForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput) password_confirm = forms.CharField(widget=forms.PasswordInput) class Meta: model = CustomUser fields = ['email', 'name'] def clean(self): cleaned_data = super().clean() password = cleaned_data.get('password') password_confirm = cleaned_data.get('password_confirm') if password != password_confirm: raise forms.ValidationError("Passwords do not match") return cleaned_data def save(self, commit=True): # 调用UserManager的create_user方法创建用户 user = CustomUser.objects.create_user( email=self.cleaned_data['email'], password=self.cleaned_data['password'], name=self.cleaned_data['name'] ) return user
方法二:在CreateView中重写form_valid方法
from django.views.generic.edit import CreateView from .models import CustomUser from .forms import CustomUserCreationForm class UserCreateView(CreateView): model = CustomUser form_class = CustomUserCreationForm success_url = '/login/' def form_valid(self, form): # 从表单获取数据,调用create_user创建用户 email = form.cleaned_data['email'] password = form.cleaned_data['password'] name = form.cleaned_data['name'] CustomUser.objects.create_user(email=email, password=password, name=name) return super().form_valid(form)
4. 检查Admin配置
确保Admin中正确配置自定义用户模型,密码字段显示正常:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import CustomUser class CustomUserAdmin(UserAdmin): model = CustomUser list_display = ['email', 'name', 'is_staff'] fieldsets = ( (None, {'fields': ('email', 'password')}), ('Personal info', {'fields': ('name',)}), ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}), ('Important dates', {'fields': ('last_login', 'date_joined')}), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'name', 'password1', 'password2'), }), ) search_fields = ['email', 'name'] ordering = ['email'] admin.site.register(CustomUser, CustomUserAdmin)
额外注意事项
- 删除之前创建的无效用户记录,重新创建测试
- 确保
settings.py中已配置AUTH_USER_MODEL = 'your_app.CustomUser' - 修改用户模型后,执行
python manage.py makemigrations和python manage.py migrate更新数据库
内容的提问来源于stack exchange,提问作者Help
相关产品推荐
相关产品推荐

