Django 4.1.1自定义用户模型登录功能失效的解决方法
问题说明
我正在使用Django 4.1.1开发教育网站,已创建继承AbstractUser的Student自定义用户模型,注册功能可正常将用户数据存入数据库,但登录功能完全无响应,既不跳转也不返回错误。请指导如何实现能验证用户输入数据与数据库匹配并完成登录的功能。
现有代码
models.py
from django.db import models from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import UserManager class Custom(UserManager): def create_user(self, username, email=None, password=None, **extra_fields): return self._create_user(username, email, password, **extra_fields) class Student(AbstractUser): objects = Custom() sex = models.CharField(max_length=50,default='male') is_superuser = None is_staff = None groups = None user_permissions = None class Meta: verbose_name = "Student" verbose_name_plural = "Students" def __str__(self): return self.username
注册表单HTML
{% load static %} <html> <link rel="stylesheet" href="{% static 'css/register.css' %}"> <form method="post"> {% csrf_token %} <input type="text" name="firstName" placeholder="First Name" required minlength="3" maxlength="30"> <input type="text" name="lastName" placeholder="Last Name" required minlength="3" maxlength="30"> <input type="text" name="username" placeholder="Username" required minlength="3" maxlength="30"> <small>{{error}}</small> <input type="email" name="email" placeholder="Email" required maxlength="64"> <small>{{error}}</small> <input type="password" name="password" placeholder="Password" required minlength="8" maxlength="32"> <input type="password" name="passwordAgain" placeholder="Confirm Password" required minlength="8" maxlength="32"> <small>{{paswword_error}}</small> <input type="radio" name="sex" value="male" checked>Male</input> <input type="radio" name="sex" value="female">Female</input> <button type="submit">Submit</button> </form> <script src="{% static 'js/register.js' %}"></script> </html>
views.py
from django.shortcuts import render,redirect from django.http import HttpResponse from .models import Student from django.contrib.auth import authenticate,login,logout # Create your views here. def home(request): # return HttpResponse('This is The Home Page !') return render(request, 'home/index.html') def register(request): if request.method == 'POST': firstName = request.POST['firstName'] lastName = request.POST['lastName'] username = request.POST['username'] email = request.POST['email'] password = request.POST['password'] passwordAgain = request.POST['passwordAgain'] sex = request.POST['sex'] if Student.objects.filter(username=username).exists() or Student.objects.filter(email=email).exists() or password != passwordAgain: error = "Alrady Taken" paswword_error = "Paswwords Don't Match" return render(request,'register/register.html',{'error':error,'paswword_error':paswword_error}) else: user = Student.objects.create_user(username,email,password) user.first_name = firstName user.last_name = lastName user.sex = sex user.save() return redirect('login') return render(request,'register/register.html') def login(request): if request.method == 'Post': username = request.POST['username'] password = request.POST['password'] user = authenticate(request,username=username,password=password) if user is not None: login(request,user) return redirect('home') else: return HttpResponse('error') return render(request, 'login/login.html')
问题排查与修复步骤
1. 视图函数名与内置函数冲突
你导入了django.contrib.auth中的login函数,但同时定义了同名的视图函数def login(request):,这会导致调用login(request, user)时实际调用的是你自己的视图函数,而非Django内置的登录认证函数,直接引发错误。
修复:将视图函数名改为user_login(或其他不冲突的名称),同时更新URL配置中的对应路由名称。
2. 请求方法判断大小写错误
Django中请求方法均为大写,代码中request.method == 'Post'的判断永远不会成立,导致POST请求进来后直接走渲染模板的分支,没有执行登录逻辑。
修复:将判断条件改为request.method == 'POST'。
3. 未配置自定义用户模型
使用自定义用户模型时,必须在settings.py中指定AUTH_USER_MODEL,否则Django的认证系统会默认使用原生User模型,导致authenticate无法正确识别你的Student用户。
修复:在settings.py中添加:
AUTH_USER_MODEL = '你的应用名.Student' # 替换成实际的应用名称
4. 登录表单完整性检查
确保登录模板(login/login.html)的表单结构正确:
- 表单
method设为post - 包含
{% csrf_token %}标签 - 用户名和密码输入框的
name属性分别为username和password
示例登录模板:
{% load static %} <html> <link rel="stylesheet" href="{% static 'css/login.css' %}"> <form method="post"> {% csrf_token %} <input type="text" name="username" placeholder="Username" required> <input type="password" name="password" placeholder="Password" required> {% if login_error %} <small>{{ login_error }}</small> {% endif %} <button type="submit">Login</button> </form> </html>
5. 完善错误返回逻辑
原代码中错误时直接返回HttpResponse('error'),用户体验差,建议将错误信息传入模板展示。
修改后的完整views.py代码
from django.shortcuts import render,redirect from django.http import HttpResponse from .models import Student from django.contrib.auth import authenticate, login, logout # Create your views here. def home(request): return render(request, 'home/index.html') def register(request): if request.method == 'POST': firstName = request.POST['firstName'] lastName = request.POST['lastName'] username = request.POST['username'] email = request.POST['email'] password = request.POST['password'] passwordAgain = request.POST['passwordAgain'] sex = request.POST['sex'] error = None paswword_error = None if Student.objects.filter(username=username).exists() or Student.objects.filter(email=email).exists(): error = "用户名或邮箱已被占用" if password != passwordAgain: paswword_error = "两次输入的密码不一致" if error or paswword_error: return render(request,'register/register.html',{'error':error,'paswword_error':paswword_error}) user = Student.objects.create_user(username, email, password) user.first_name = firstName user.last_name = lastName user.sex = sex user.save() return redirect('user_login') return render(request,'register/register.html') def user_login(request): login_error = None if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) return redirect('home') else: login_error = "用户名或密码错误" return render(request, 'login/login.html', {'login_error': login_error})
最后更新URL配置
确保URL路由中,登录对应的名称改为user_login:
# urls.py示例 from django.urls import path from . import views urlpatterns = [ path('', views.home, name='home'), path('register/', views.register, name='register'), path('login/', views.user_login, name='user_login'), ]
内容的提问来源于stack exchange,提问作者kimanxo 313

