以下文章是 Django 类基视图(CBV)探索系列的 第七篇,讨论如何利用 Mixin 来 重用通用功能,并有效实现 权限管理 和 登录检查。在上一篇文章(第六篇)中,我们已通过 TemplateView
和 RedirectView
实现了简单的页面渲染和重定向的自动化,现在将了解如何最大化 CBV 的 重用性 和 扩展性。
上一篇的直接链接请点击以下链接!
TemplateView & RedirectView 的利用方法
“通过 Django Mixin 提高代码的重用性,
简洁地实现权限和登录检查!”
1. Mixin,为什么需要?
Django CBV 本身提供了强大的重用性,但如果多个视图中存在 普遍需要的功能,该如何处理呢?例如,访问某个页面常常需要 登录,或者只有具有 特定权限 的用户才能访问。这时就引入了 Mixin 的概念。
Mixin 是利用 多重继承 的概念,将 相同的方法或属性注入 到多个类中。在 Django CBV 中,通过将实现了特定功能的 Mixin 类继承给视图类,可以减少 重复代码,并提高 可维护性。
主要 Mixin 的使用示例:
- 权限管理:检查访问特定视图的用户是否已登录,或是否具有特定权限。
- 表单处理逻辑:在多个表单中通用的数据预处理或后处理逻辑。
- 模板上下文:为所有视图添加需要共同传递的上下文数据。
- 日志记录:在特定视图的执行前后添加日志记录功能。
2. Django 的代表性 Mixin 使用法:LoginRequiredMixin
最常用的 Mixin 之一就是 LoginRequiredMixin
。顾名思义,它的作用是强制要求用户在访问该视图时 必须登录。
2.1 LoginRequiredMixin 的使用方法
LoginRequiredMixin
包含在 django.contrib.auth.mixins
模块中。
# views.py
from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Post # 示例模型
class MyPostListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'posts/my_posts.html'
context_object_name = 'posts'
# 未登录用户访问时重定向的 URL 设置(可选)
# login_url = '/accounts/login/' # settings.LOGIN_URL 为默认值
# redirect_field_name = 'next' # 登录后返回原页面时使用的查询参数名(默认为 next)
- 继承顺序:首先继承
LoginRequiredMixin
,然后继承 Django 的通用视图(这里是ListView
)。Mixin 主要用于添加功能,因此通常将其放在核心视图类之前。 LoginRequiredMixin
会自动将未登录用户重定向到指定的settings.LOGIN_URL
登录页面。登录成功后会通过next
查询参数返回到原请求的页面。
2.2 urls.py 的连接
应用了 LoginRequiredMixin
的视图与普通 CBV 连接在 urls.py
中是相同的。
# urls.py
from django.urls import path
from .views import MyPostListView
urlpatterns = [
path('my-posts/', MyPostListView.as_view(), name='my_posts'),
]
现在访问 /my-posts/
路径时,如果未登录,则会自动转到登录页面。
3. 权限管理的 Mixin:PermissionRequiredMixin & UserPassesTestMixin
如果 LoginRequiredMixin
是强制要求用户登录,那么 PermissionRequiredMixin
和 UserPassesTestMixin
则允许基于 特定权限 或 特定条件 来访问。
3.1 PermissionRequiredMixin 的使用方法
基于 Django 的权限系统,只有具有特定 permission
的用户才能访问。
# views.py
from django.views.generic import CreateView
from django.contrib.auth.mixins import PermissionRequiredMixin
from .models import Article
from .forms import ArticleForm
class ArticleCreateView(PermissionRequiredMixin, CreateView):
model = Article
form_class = ArticleForm
template_name = 'articles/article_form.html'
success_url = '/articles/'
# 通过 'app_label.permission_codename' 格式指定权限
permission_required = 'app_label.add_article'
# 若任一权限存在则允许访问:
# permission_required = ('app_label.add_article', 'app_label.change_article')
# raise_exception = True # 无权限时抛出 403 Forbidden 错误(默认重定向到登录页面)
permission_required
:以字符串(一个或元组)形式指定访问所需的权限。通常使用 Djangoauth
应用自动生成的权限(add_model
,change_model
,delete_model
,view_model
)。
3.2 UserPassesTestMixin 的使用方法
当希望检查更 复杂或自定义的条件 时使用。例如,可以实现只能修改自己写的文章,或只允许特定组用户访问等逻辑。
# views.py
from django.views.generic import UpdateView
from django.contrib.auth.mixins import UserPassesTestMixin
from .models import Comment
from .forms import CommentForm
class CommentUpdateView(UserPassesTestMixin, UpdateView):
model = Comment
form_class = CommentForm
template_name = 'comments/comment_form.html'
success_url = '/comments/'
# 重写 test_func 方法以检查条件
def test_func(self):
comment = self.get_object()
# 检查当前登录用户是否是评论的作者
return self.request.user == comment.author or self.request.user.is_superuser
# raise_exception = True # 测试失败时抛出 403 Forbidden 错误
test_func()
方法如果返回 True 则允许访问,如果返回 False 则拒绝访问。self.request.user
可以访问当前登录的用户对象。
4. 自定义 Mixin 的创建
除了 Django 提供的 Mixin 外,还可以创建 自定义 Mixin 在多个视图中重用。例如,创建一个添加所有页面通用的 current_year
上下文的 Mixin。
# common/mixins.py
from datetime import datetime
class CurrentYearMixin:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['current_year'] = datetime.now().year
return context
# views.py (应用示例)
from django.views.generic import TemplateView
from .common.mixins import CurrentYearMixin
class MyCustomPageView(CurrentYearMixin, TemplateView):
template_name = 'my_custom_page.html'
# my_custom_page.html (模板中使用)
<footer>© {{ current_year }} 我的官方网站</footer>
CurrentYearMixin
通过重写get_context_data
方法来添加current_year
到上下文中。调用super().get_context_data(**kwargs)
是为了保持上层类(或其他 Mixin)的上下文数据非常重要。
5. 与 FBV 对比
功能 | FBV(基于函数的视图) | CBV + Mixin |
登录/权限检查 | 使用 @login_required , @permission_required 装饰器。 <br> 自定义条件通常在函数内手动编写 if not request.user.is_authenticated: return redirect(...) 等。 |
通过继承 LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin 等 Mixin 轻松实现。 <br> 类似于装饰器,但更与 CBV 结构整合。 |
代码重用性 | 通过调用单独的函数或手动编写函数装饰器来隔离通用逻辑。 <br> 容易产生重复代码。 | 通过 Mixin 模块化所需的功能并通过多重继承注入。 <br> 结构化程度更高且重用性更强。 |
代码可读性 | 每个函数中条件检查逻辑可能重复。 | 仅需查看视图类的继承列表,即可理解应用了哪些功能(权限、登录等)。 |
可维护性 | 添加新功能时可能需要修改多个函数。 | 仅需修改 Mixin 类,所有使用该 Mixin 的视图会自动生效。 |
开发生产力(核心关键词) | “每个函数的独立处理,重复工作的可能性” | “模块化,功能扩展容易,遵循 DRY(不要重复自己)原则,提高生产力” |
6. 结论及下篇预告
Mixin 是 Django 类基视图的 真正力量 的关键要素。通过它,我们可以最大化 代码的重用性,模块化 通用功能,以简化视图类的复杂性,尤其是像 认证和权限管理 这样的 Web 应用必要元素能够非常高效地实现。
现在我们已经探讨了从 CBV 的基本用法到复杂的 CRUD,以及通过 Mixin 扩展功能,几乎涵盖了 Django CBV 的所有核心。
在下一篇(系列第八篇)中,我们将讨论如何将之前讨论的 CBV 实际应用于项目,以及在 复杂场景中 如何组合使用,并综合总结 CBV 的优点和局限性,结束本系列。
查看上一篇内容
- 类基视图(CBV)探索系列 #1 – 从 FBV 到 CBV 的原因以及开发者的态度
- 类基视图(CBV)探索系列 #2 – 了解 Django 的基本视图类
- 类基视图(CBV)探索系列 #3 – 使用 FormView 简化表单处理
- 类基视图(CBV)探索系列 #4 – ListView & DetailView 的利用方法
- 类基视图(CBV)探索系列 #5 – 使用 CreateView、UpdateView、DeleteView 实现 CRUD
- 类基视图(CBV)探索系列 #6 – TemplateView & RedirectView 的利用方法
“利用 Mixin 发挥 Django CBV 的潜力,
构建易于维护和扩展的 Web 应用!”
目前没有评论。