如何在Django中使用不同数据表实现身份验证?
Django 多表身份验证实现(对应Laravel Auth Guard)
核心业务逻辑
- 为普通用户和管理员分别定义独立的自定义用户模型,继承Django认证体系基类,保留密码加密、权限管理等原生功能。
- 编写对应模型的认证后端,让Django能针对不同模型执行身份校验。
- 为两类用户分别编写登录视图,指定对应的认证后端完成登录流程。
- 配置项目支持多认证后端,实现不同入口的身份验证分流。
代码实现步骤
1. 定义自定义用户模型(models.py)
分别创建User(普通用户)和Admin(管理员)模型,均继承AbstractBaseUser和PermissionsMixin,实现必要字段和管理器:
普通用户模型
from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager class UserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('必须填写邮箱') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) 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('超级用户必须设置is_staff=True') if extra_fields.get('is_superuser') is not True: raise ValueError('超级用户必须设置is_superuser=True') return self.create_user(email, password, **extra_fields) class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] def __str__(self): return self.email
管理员模型
class AdminManager(BaseUserManager): def create_admin(self, email, password=None, **extra_fields): if not email: raise ValueError('必须填写邮箱') email = self.normalize_email(email) admin = self.model(email=email, **extra_fields) admin.set_password(password) admin.save(using=self._db) return admin def create_superadmin(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('超级管理员必须设置is_staff=True') if extra_fields.get('is_superuser') is not True: raise ValueError('超级管理员必须设置is_superuser=True') return self.create_admin(email, password, **extra_fields) class Admin(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=True) # 管理员默认具备后台访问权限 objects = AdminManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] def __str__(self): return self.email
2. 自定义认证后端(backends.py)
创建两个认证后端,分别对应Admin和User模型,实现authenticate和get_user方法:
from django.contrib.auth.backends import ModelBackend from .models import Admin, User class AdminBackend(ModelBackend): def authenticate(self, request, email=None, password=None, **kwargs): try: admin = Admin.objects.get(email=email) if admin.check_password(password) and admin.is_active: return admin except Admin.DoesNotExist: return None def get_user(self, user_id): try: return Admin.objects.get(pk=user_id) except Admin.DoesNotExist: return None class UserBackend(ModelBackend): def authenticate(self, request, email=None, password=None, **kwargs): try: user = User.objects.get(email=email) if user.check_password(password) and user.is_active: 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
3. 配置认证后端(settings.py)
在项目配置中添加自定义的认证后端:
AUTHENTICATION_BACKENDS = [ 'your_app_name.backends.AdminBackend', 'your_app_name.backends.UserBackend', # 若需保留默认auth_user表的认证,可取消下方注释 # 'django.contrib.auth.backends.ModelBackend', ]
4. 编写登录视图(views.py)
为管理员和普通用户分别编写登录视图,指定对应的认证后端完成校验:
from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from django.contrib import messages def admin_login(request): if request.method == 'POST': email = request.POST['email'] password = request.POST['password'] # 指定使用管理员认证后端 admin = authenticate(request, email=email, password=password, backend='your_app_name.backends.AdminBackend') if admin: login(request, admin) return redirect('admin_dashboard') # 跳转到管理员后台页面 messages.error(request, '邮箱或密码错误') return render(request, 'admin_login.html') def user_login(request): if request.method == 'POST': email = request.POST['email'] password = request.POST['password'] # 指定使用普通用户认证后端 user = authenticate(request, email=email, password=password, backend='your_app_name.backends.UserBackend') if user: login(request, user) return redirect('user_dashboard') # 跳转到用户前台页面 messages.error(request, '邮箱或密码错误') return render(request, 'user_login.html')
5. 配置路由(urls.py)
添加登录路由:
from django.urls import path from . import views urlpatterns = [ path('admin/login/', views.admin_login, name='admin_login'), path('user/login/', views.user_login, name='user_login'), # 管理员后台、用户前台路由示例 path('admin/dashboard/', views.admin_dashboard, name='admin_dashboard'), path('user/dashboard/', views.user_dashboard, name='user_dashboard'), ]
6. 权限控制示例
如果需要限制页面访问权限,可使用user_passes_test装饰器校验用户类型:
from django.contrib.auth.decorators import user_passes_test def is_admin(user): return isinstance(user, Admin) @user_passes_test(is_admin) def admin_dashboard(request): return render(request, 'admin_dashboard.html')
注意事项
- 完成模型定义后,需执行数据库迁移:
python manage.py makemigrations和python manage.py migrate - 自行编写登录模板(
admin_login.html、user_login.html),确保表单提交到对应路由 - 若需使用Django admin后台,需为
Admin模型注册到admin站点
内容的提问来源于stack exchange,提问作者user15539888
相关产品推荐
相关产品推荐

