📌  相关文章
📜  基于类和基于函数的视图——在 Django 中使用哪个更好?

📅  最后修改于: 2021-10-19 08:03:21             🧑  作者: Mango

Django …我们都知道这个Python框架在世界范围内的流行。这个框架使开发人员的生活更轻松。开发人员在 Django 中构建成熟的 Web 应用程序变得更加容易。如果您是一位经验丰富的 Django 开发人员,那么您肯定已经了解该项目的流程。 Django 样板文件中的运行方式以及数据如何呈现给用户。

基于类与基于函数的视图

Django 在 MVT 概念上工作,我们主要在其中处理两种类型的视图……基于类的视图和基于函数的视图。如果您是 Django 框架的新手,那么您肯定一直在使用 FBV(基于函数的视图)。

最初, Django以基于函数的视图开始,但后来 Django 添加了基于类的视图的概念,以避免样板中的代码冗余。开发人员之间争论不休,哪个更适合在 Django 中使用……基于类的视图还是基于函数的视图?今天在这篇博客中,我们将深入讨论这个话题,以了解两种观点的优缺点。

您可以使用它们来完成您的任务。有些任务可以使用 CBV 最好地实现,而其中一些任务可以在 FBV 中实现。 Django 视图主要有三个要求……

  • 它们是可调用的。您可以使用基于函数或基于类的方式编写视图。使用 CBV 时,您会继承 as_view() 方法,该方法使用 dispatch() 方法调用适合的方法,具体取决于 HTTP 动词(get、post)等。
  • 作为第一个位置参数,Django 视图应该接受 HttpRequest。
  • 它应该返回 HttpResponse对象,或者应该引发异常。

现在让我们比较这两种观点,看看它们的优缺点。

1. 基于函数的视图

基于函数的视图非常适合初学者。与基于类的视图相比,它很容易理解。最初,当您想专注于核心基础知识时,使用基于函数的视图有利于理解它。让我们讨论一下它的一些优点和缺点。

优点:

  • 易于阅读、理解和实施。
  • 显式代码流
  • 装饰器的直接使用。
  • 适合专门的功能。

缺点:

  • 代码冗余且难以扩展
  • 条件分支将用于处理 HTTP 方法。

正如我们所讨论的,基于函数的视图很容易理解,但由于大型 Django 项目中的代码冗余,您会在视图中发现类似的函数。你会发现类似的代码被不必要地重复了。

这是基于函数的视图的示例……

Python3
def example_create_view(request, pk):
  template_name = 'form.html'
  form_class = FormExample
  
  form = form_class
  
  if request.method == 'POST':
    form = form_class(request.POST)
    if form.is_valid():
      form.save()
      return HttpResponseRedirect(reverse('list-view'))
  
  return render(request, template_name, {'form': form})


Python3
class MyCreateView(View):
  template_name = 'form.html'
  form_class = MyForm
  
  def get(self, request, *args, **kwargs):
    form = self.form_class
    return render(request, template_name, {'form': form})
  
  def post(self, request, *args, **kwargs):
    form = self.form_class(request.POST)
    if form.is_valid():
      form.save()
      return HttpResonseRedirect(reverse('list-view'))
    else:
      return render(request, self.template_name, {'form': form})


Python3
urlpatterns = [
    url(r'^new/$', MyCreateView.as_view(), name='original-create-view')
    url(r'^new_two/$', MyCreateView.as_view(template_name='other_form.html',
                    form_class='MyOtherForm'), name='modified-create-view')
  ]


Python3
from django.views.generic import CreateView 
class MyCreateView(CreateView):
    model = MyModel  
    form_class = MyForm


Python3
from django import forms
from . models import MyModel 
class MyModelForm(forms.ModelForm):
  class Meta:
    model = MyModel
    fields = ['name', 'description']


您在基于类的视图中找不到 FBV 的所有上述缺点。您不必在样板中一遍又一遍地编写相同的代码。

2. 基于类的视图

基于类的视图是基于函数的视图的替代品。它在项目中作为Python对象而不是函数实现。基于类的视图不会取代基于函数的视图,但与基于函数的视图相比,它们确实具有某些优势。基于类的视图负责基本功能,例如删除项目或添加项目。

如果您是初学者,使用基于类的视图并不容易。您必须仔细阅读文档,并且必须正确地研究它。一旦您了解了 Django 中的基于函数的视图并且您的概念清晰,您就可以转向基于类的视图。让我们详细讨论基于类的视图。

优点

  • 基于类的视图最显着的优点是继承。在基于类的视图中,您可以继承另一个类,并且可以针对不同的用例对其进行修改。
  • 它可以帮助您遵循 DRY 原则。您不必在样板中一遍又一遍地编写相同的代码。在基于类的视图中代码可重用性是可能的。
  • 您可以扩展基于类的视图,并且可以使用 Mixin 添加更多功能。
  • 使用基于类的视图的另一个优点是代码结构化。在基于类的视图中,您可以使用不同的类实例方法(而不是基于函数的视图中的条件分支语句)来生成不同的 HTTP 请求。
  • 内置通用的基于类的视图。

缺点

  • 实施复杂且难以阅读
  • 隐式代码流。
  • 视图装饰器中需要额外的导入或方法覆盖。

下面是一个基于类的视图的例子……

蟒蛇3

class MyCreateView(View):
  template_name = 'form.html'
  form_class = MyForm
  
  def get(self, request, *args, **kwargs):
    form = self.form_class
    return render(request, template_name, {'form': form})
  
  def post(self, request, *args, **kwargs):
    form = self.form_class(request.POST)
    if form.is_valid():
      form.save()
      return HttpResonseRedirect(reverse('list-view'))
    else:
      return render(request, self.template_name, {'form': form})

我们有一些抽象,方法 as_view() 正在调用 dispatch() 来确定需要执行哪个类方法,具体取决于 HTTP 请求。 as_view() 允许您覆盖 URL confs 中的类属性。您可以执行以下操作…

蟒蛇3

urlpatterns = [
    url(r'^new/$', MyCreateView.as_view(), name='original-create-view')
    url(r'^new_two/$', MyCreateView.as_view(template_name='other_form.html',
                    form_class='MyOtherForm'), name='modified-create-view')
  ]

一旦您开始使用 Django 通用的基于类的视图,您将能够覆盖像 get_form_class 和 get_template_names 这样的辅助方法。您可以在这些点插入附加逻辑,而不仅仅是覆盖类属性。

一个很好的例子是……ModelFormMixin。 form_valid 方法被覆盖。使用存储在 self.object() 中的更新值 form_valid 方法被覆盖。

3. Django 通用的基于类的视图

创建新对象、表单处理、列表视图、分页、存档视图所有这些都是 Web 应用程序中的常见用例。它来自 Django 核心,您可以从模块 django.views.generic 中实现它们。通用的基于类的视图是执行所有这些任务的绝佳选择。它加快了开发过程。

Django 提供了一组视图、mixin 和基于类的通用视图。利用它,您可以解决 Web 开发中最常见的任务。

主要目标不是减少样板。它使您免于一次又一次地编写相同的代码。修改 MyCreateView 继承自 django.views.generic.CreateView。

蟒蛇3

from django.views.generic import CreateView 
class MyCreateView(CreateView):
    model = MyModel  
    form_class = MyForm

您可能会认为所有代码都消失了。答案是这一切都在 django.views.generic.CreateView 中。当您从 CreateView 继承时,您将获得许多功能和快捷方式。您也认同某种“约定胜于配置”。风格安排。让我们再讨论一些细节……

默认情况下,模板应位于//_form.html。您可以通过设置类属性template_nametemplate_name_suffix来更改它

  • 我们还需要声明 model 和 form_class 属性。从 CreateView 继承的方法依赖于它们。
  • 您必须将 success_url 声明为视图上的类属性,或者必须在模型中指定get_absolute_url() 。这对于样板中的视图很重要,否则视图将不知道在成功提交表单后重定向到哪里。
  • 在表单中定义字段或在视图上指定字段类属性。在此示例中,您可以选择执行后者。

查看下面给出的示例以检查它的外观。

蟒蛇3

from django import forms
from . models import MyModel 
class MyModelForm(forms.ModelForm):
  class Meta:
    model = MyModel
    fields = ['name', 'description']

结论

开发人员之间仍然争论哪种好用。基于类的视图还是基于函数的视图?我们已经讨论了它们的优缺点,但这完全取决于上下文和需求。我们已经提到基于类的视图不会取代基于函数的视图。在某些情况下,基于函数的视图更好,而在某些情况下,基于类的视图更好。

在列表视图的实现中,您可以通过继承 ListView 并覆盖属性来使其工作。在您需要执行更复杂的操作,同时处理多个表单的场景中,基于函数的视图将是您更好的选择。