Django注册后无法登录问题修复请求(含自定义手机号字段)
问题分析与修复方案
你登录失败的核心原因是用户模型字段冲突、密码存储逻辑错误,以及表单与模型字段不匹配,下面是分步修复:
1. 修复用户模型(models.py)
继承AbstractUser时,它已经自带first_name、last_name、password等字段,你重复定义的字段会覆盖系统默认的密码存储逻辑,导致认证失败。同时需要设置用邮箱作为登录凭证:
from django.contrib.auth.models import AbstractUser from django.db import models CHARS_MAX_LENGTH = 255 # 确保这个常量已定义 class User(AbstractUser): # 移除重复的firstname、lastname、password,使用AbstractUser自带字段 email = models.EmailField(max_length=CHARS_MAX_LENGTH, blank=False, unique=True) phone = models.CharField(max_length=20, blank=False) # 手机号用CharField更合适 # 设置登录时使用邮箱作为用户名 USERNAME_FIELD = 'email' # 注册时必填的额外字段(除了邮箱和密码) REQUIRED_FIELDS = ['first_name', 'last_name', 'phone', 'username']
2. 修复注册表单(forms.py)
利用BaseUserCreationForm自带的密码验证逻辑,移除重复的密码字段,确保表单字段与模型对应:
from django.contrib.auth.forms import BaseUserCreationForm from django import forms from django.contrib.auth import get_user_model User = get_user_model() class UserCreationForm(BaseUserCreationForm): first_name = forms.CharField(max_length=50, required=True, label="First name") last_name = forms.CharField(max_length=50, required=True, label="Last name") email = forms.EmailField(label="Email Address") phone = forms.CharField(max_length=20, required=True, label="Phone number") class Meta: model = User fields = ('first_name', 'last_name', 'email', 'phone', 'password1', 'password2') def clean_email(self): # 单独验证邮箱是否已存在 email = self.cleaned_data.get('email') if User.objects.filter(email=email).exists(): raise forms.ValidationError("Email already exists") return email # 添加登录表单 class LoginForm(forms.Form): email = forms.EmailField(label="Email Address") password = forms.CharField(label="Password", widget=forms.PasswordInput)
3. 修复注册视图(views.py)
使用表单的save()方法创建用户,自动处理密码哈希,避免手动赋值出错:
from django.shortcuts import render, redirect from django.contrib.auth import login, authenticate from .forms import UserCreationForm, LoginForm def register_view(request): """Registration view.""" if request.method == 'GET': register_form = UserCreationForm() return render(request, 'netflix/register.html', {'register_form': register_form}) else: register_form = UserCreationForm(request.POST) if register_form.is_valid(): user = register_form.save(commit=False) user.username = user.email # 保持用户名与邮箱一致 user.save() return redirect('/login') return render(request, 'netflix/register.html', {'register_form': register_form}) def login_view(request): # Login view. if request.method == 'GET': login_form = LoginForm() return render(request, 'netflix/login.html', {'login_form': login_form}) else: email = request.POST.get('email') password = request.POST.get('password') # 基于邮箱认证用户 user = authenticate(request, username=email, password=password) if user is not None: login(request, user) return redirect('/logged_in') return render( request, 'netflix/login.html', { 'wrong_credentials': True, 'login_form': LoginForm(request.POST) } )
4. 最后必须执行的操作
- 在
settings.py中配置自定义用户模型:
AUTH_USER_MODEL = 'netflix.User' # 替换成你的app名称
- 执行数据库迁移:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者Imamudin Johar
相关产品推荐
相关产品推荐

