如何基于数据库自定义user表实现Django登录功能?
解决方案
1. 自定义认证后端(核心适配逻辑)
你的自定义user表和明文密码的存储方式,导致Django默认认证系统无法识别普通用户,必须写一个自定义认证后端来适配:
在你的App目录下创建backends.py文件,写入以下代码:
from django.contrib.auth.backends import BaseBackend from .models import User # 导入映射后的自定义User模型 class CustomUserBackend(BaseBackend): def authenticate(self, request, login=None, password=None, **kwargs): try: # 根据login字段查询用户 user = User.objects.get(login=login) # 明文密码直接比对 if user.password == password: return user except User.DoesNotExist: return None def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
在settings.py中配置启用这个后端:
AUTHENTICATION_BACKENDS = [ 'your_app_name.backends.CustomUserBackend', # 替换为你的App名称 'django.contrib.auth.backends.ModelBackend', # 保留默认后端,兼容超级用户登录 ]
2. 映射现有user表到Django模型
如果还没在Models中绑定现有表,先创建对应模型:
from django.db import models class User(models.Model): login = models.CharField(max_length=100, unique=True) password = models.CharField(max_length=100) name = models.CharField(max_length=100) class Meta: db_table = 'user' # 指定对应数据库中的表名
3. 自定义视图实现登录
修改你的自定义视图,调用authenticate时传入login和password参数:
from django.contrib.auth import authenticate, login from django.shortcuts import render, redirect def user_login(request): if request.method == 'POST': login_account = request.POST.get('login') login_pwd = request.POST.get('password') # 用自定义后端验证用户 user = authenticate(request, login=login_account, password=login_pwd) if user: login(request, user) return redirect('home') # 替换为登录成功后的跳转页面 else: return render(request, 'login.html', {'error': '账号或密码错误'}) return render(request, 'login.html')
对应的登录模板login.html示例:
<form method="post"> {% csrf_token %} <div> <label>账号:</label> <input type="text" name="login" required> </div> <div> <label>密码:</label> <input type="password" name="password" required> </div> {% if error %} <p style="color:red">{{ error }}</p> {% endif %} <button type="submit">登录</button> </form>
4. 使用Django自带LoginView实现
如果想用官方LoginView,需要自定义登录表单适配login字段:
在App目录下创建forms.py:
from django.contrib.auth.forms import AuthenticationForm class CustomLoginForm(AuthenticationForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 将默认的username字段改名为login并修改提示 self.fields['username'].name = 'login' self.fields['username'].label = '账号'
在urls.py中配置LoginView:
from django.contrib.auth.views import LoginView from .forms import CustomLoginForm urlpatterns = [ path('login/', LoginView.as_view( template_name='login.html', authentication_form=CustomLoginForm ), name='login'), ]
重要提醒
- 明文密码存在严重安全风险,建议后续迁移为Django哈希存储:通过
user.set_password(明文密码)生成哈希后更新数据库,然后将认证后端的密码比对逻辑改为user.check_password(password)。 - 确保
user表的login字段唯一,避免查询时出现多用户匹配的问题。
内容的提问来源于stack exchange,提问作者Gandoplas
相关产品推荐
相关产品推荐

