第9章:用户认证系统
9.1 Django认证框架
User模型
Django内置了强大的用户认证系统,核心是User模型。User模型包含以下字段:
python
# Django内置User模型的主要字段
class User(models.Model):
username = models.CharField(max_length=150, unique=True)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
email = models.EmailField(blank=True)
is_staff = models.BooleanField(default=False) # 是否可以访问admin
is_active = models.BooleanField(default=True) # 是否激活
is_superuser = models.BooleanField(default=False) # 是否是超级用户
last_login = models.DateTimeField(blank=True, null=True)
date_joined = models.DateTimeField(default=timezone.now)使用User模型的基本操作:
python
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
# 创建用户
user = User.objects.create_user(
username='john',
email='john@example.com',
password='secret'
)
# 创建超级用户
superuser = User.objects.create_superuser(
username='admin',
email='admin@example.com',
password='secret'
)
# 验证用户
user = authenticate(username='john', password='secret')
if user is not None:
print("用户验证成功")
else:
print("用户名或密码错误")
# 修改用户属性
user.first_name = 'John'
user.last_name = 'Doe'
user.save()
# 设置密码
user.set_password('newpassword')
user.save()
# 检查密码
if user.check_password('newpassword'):
print("密码正确")扩展User模型:
python
# 方法1:一对一关联(推荐)
from django.contrib.auth.models import User
from django.db import models
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True)
# 创建用户配置文件的信号处理器
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userprofile.save()
# 方法2:自定义User模型
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
# 在settings.py中设置
AUTH_USER_MODEL = 'myapp.CustomUser'认证视图
Django提供了内置的认证视图来处理常见的认证任务:
python
# urls.py
from django.urls import path, include
from django.contrib.auth import views as auth_views
urlpatterns = [
# 使用Django内置认证视图
path('accounts/', include('django.contrib.auth.urls')),
# 或者单独定义每个视图
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]自定义登录视图:
python
# views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages
def custom_login(request):
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, f"欢迎您,{username}!")
return redirect('home')
else:
messages.error(request, "用户名或密码错误")
else:
messages.error(request, "用户名或密码错误")
else:
form = AuthenticationForm()
return render(request, 'registration/login.html', {'form': form})
# 自定义登录模板 registration/login.html
"""
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">登录</button>
</form>
"""权限系统
Django的权限系统基于用户、组和权限的模型:
python
from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType
from myapp.models import Article
# 创建权限
content_type = ContentType.objects.get_for_model(Article)
permission = Permission.objects.create(
codename='can_publish_article',
name='Can Publish Article',
content_type=content_type,
)
# 为用户分配权限
user = User.objects.get(username='john')
user.user_permissions.add(permission)
# 为组分配权限
group = Group.objects.get(name='Editors')
group.permissions.add(permission)
# 将用户添加到组
user.groups.add(group)
# 检查用户权限
if user.has_perm('myapp.can_publish_article'):
print("用户有发布文章的权限")
# 检查用户是否属于某个组
if user.groups.filter(name='Editors').exists():
print("用户是编辑")
# 在视图中检查权限
from django.contrib.auth.decorators import permission_required
@permission_required('myapp.can_publish_article')
def publish_article(request):
# 只有具有发布权限的用户才能访问
pass
# 在类视图中检查权限
from django.contrib.auth.mixins import PermissionRequiredMixin
class PublishArticleView(PermissionRequiredMixin, CreateView):
permission_required = 'myapp.can_publish_article'
# 视图实现组管理
组是管理用户权限的有效方式:
python
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
# 创建组
editors_group = Group.objects.create(name='Editors')
writers_group = Group.objects.create(name='Writers')
# 获取权限
content_type = ContentType.objects.get_for_model(Article)
add_article_perm = Permission.objects.get(
content_type=content_type,
codename='add_article'
)
change_article_perm = Permission.objects.get(
content_type=content_type,
codename='change_article'
)
delete_article_perm = Permission.objects.get(
content_type=content_type,
codename='delete_article'
)
# 为组分配权限
editors_group.permissions.add(
add_article_perm,
change_article_perm,
delete_article_perm
)
# 将用户添加到组
user = User.objects.get(username='john')
user.groups.add(editors_group)
# 检查用户是否属于组
if user.groups.filter(name='Editors').exists():
print("用户是编辑")
# 从组中移除用户
user.groups.remove(editors_group)
# 删除组
editors_group.delete()在模板中使用权限:
html
<!-- 检查用户是否已认证 -->
{% if user.is_authenticated %}
<p>欢迎您,{{ user.username }}!</p>
<a href="{% url 'logout' %}">退出</a>
{% else %}
<a href="{% url 'login' %}">登录</a>
{% endif %}
<!-- 检查用户权限 -->
{% if perms.myapp.add_article %}
<a href="{% url 'article_create' %}">创建文章</a>
{% endif %}
<!-- 检查用户是否属于特定组 -->
{% if user.groups.all %}
<p>您的组:
{% for group in user.groups.all %}
{{ group.name }}{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
{% endif %}通过Django的认证框架,你可以轻松实现用户注册、登录、权限管理等常见的认证功能。
小结
Django认证框架提供了完整的用户管理系统:
- ✅ 内置User模型处理用户基本信息
- ✅ 支持扩展User模型以满足特定需求
- ✅ 内置认证视图简化登录/登出流程
- ✅ 基于权限和组的访问控制
- ✅ 模板中的权限检查
掌握认证框架是构建安全Web应用的基础。
下一篇
我们将学习用户注册和登录的具体实现。