轻松将 Django 基于函数的视图转换为基于类的视图
在本教程中,我将使用基于函数的视图 (FBV) 构建一个简单的笔记应用程序,并将其转换为基于类的视图 (CBV)。
本文将作为 YouTube 教程的指南,因此我建议观看完整的视频教程并参考源代码。
我们基于功能的观点
让我们先快速看一下我们目前的观点。
我们的视图文件包含用于执行创建、读取、更新和删除笔记的基本 CRUD 操作的视图。
def TaskList(request):
if request.method == 'GET':
tasks = Task.objects.all().order_by('-updated')
context = {'tasks':tasks}
return render(request, 'base/index.html', context)
if request.method == 'POST':
task = Task.objects.create(
body=request.POST.get('body')
)
task.save()
return redirect('tasks')
## ------------------------------------------------------
def TaskDetail(request, pk):
if request.method == 'GET':
task = Task.objects.get(id=pk)
context = {'task':task}
return render(request, 'base/task.html', context)
if request.method == 'POST':
task = Task.objects.get(id=pk)
task.body = request.POST.get('body')
task.save()
return redirect('tasks')
## ------------------------------------------------------
def TaskDelete(request, pk):
task = Task.objects.get(id=pk)
if request.method == 'POST':
task.delete()
return redirect('tasks')
context = {'task':task}
return render(request, 'base/delete.html', context)
保持我们基于阶级的观点
基于类的视图之所以复杂,并非因为它们难以使用,而是因为它们存在一层抽象,这使得我们难以理解其具体运作机制以及如何修改它们。Django 提供了许多内置视图供我们选择,这有助于快速开发,但如果您不了解这些视图的来龙去脉,反而可能会感到困惑,因为底层有很多“魔法”。
因此,我不会使用内置视图,而是保持原始状态,只扩展 Django 提供的基础视图,并从头开始编写所有逻辑,这样您就可以看到基于类的视图与基于函数的视图有何异同。
关于基于类的视图的一些事项
在开始之前,我想先让你了解一些关于基于类的视图的知识。
扩展基类 View
每个基于类的视图都继承自基View类。由于我们没有使用任何其他内置视图,请确保导入View“View”并将其传递给每个类:
from django.views import View
...
class OurView(View):
通过 HTTP 方法进行分离
使用基于类的视图,我们将代码拆分为 HTTP 动词。因此,我们无需执行类似 `get()` 这样的操作if request.method == 'POST',只需修改类post提供的方法View,让该方法处理请求时发生的一切post。请求也是如此get。
前任:
class OurView(View):
def get(self, request):
pass
def post(self, request):
pass
让我们从第一个视图开始。
任务列表视图
让我们把这个视图注释掉TaskList,然后从头开始重建它。
现在我们将视图重写为一个类,并使其继承自View该类。我们还要向这个新类添加两个方法(get& post),并确保在每个方法中都传入self参数。request
有了类和两个方法之后,让我们从基于函数的视图中提取逻辑,并根据每个 HTTP 方法将其添加到新类中,如下所示:
from django.views import View
....
class TaskList(View):
def get(self, request):
tasks = Task.objects.all().order_by('-updated')
context = {'tasks':tasks}
return render(request, 'base/index.html', context)
def post(self, request):
task = Task.objects.create(
body=request.POST.get('body')
)
task.save()
return redirect('tasks')
现在要使用此视图,我们需要在 urls.py 中引用该类,然后使用该as_view()方法。
path('', views.TaskList.as_view(), name="tasks"),
就这样,我们把第一个基于函数的视图转换成了基于类的视图!
任务详情视图
现在让我们对TaskDetail. 同样地,我们将注释掉基于函数的视图,并将所有逻辑提取出来并分离到 http 方法中。
class TaskDetail(View):
def get(self, request, pk):
task = Task.objects.get(id=pk)
context = {'task':task}
return render(request, 'base/task.html', context)
def post(self, request, pk):
task = Task.objects.get(id=pk)
task.body = request.POST.get('body')
task.save()
return redirect('tasks')
然后将其添加as_view()到调用此视图时的 URL 路径中。
path('<str:pk>/', views.TaskDetail.as_view(), name="task"),
任务删除视图
我相信你现在应该已经开始看出规律了,所以我们对“删除”视图也做同样的事情。
class TaskDelete(View):
def get(self, request, pk):
task = Task.objects.get(id=pk)
context = {'task':task}
return render(request, 'base/delete.html', context)
def post(self, request, pk):
task = Task.objects.get(id=pk)
task.delete()
return redirect('tasks')
path('<str:pk>/delete/', views.TaskDelete.as_view(), name="delete"),
让我们回顾一下我们做了什么。
对于每个视图,我们:
- 改为
defclass - 扩展了基
View类 - 按方法分离逻辑,并在请求之前
http添加。self - 添加
as_view()到每个视图中urls.py