Python技术迷

Django教程-基于 Django 类的通用视图

整理:python架构师
Django 是最流行的 Python Web 框架,用于快速 Web 应用程序开发。它提供了一个内置界面,可以轻松使用它。它也被称为包含电池的框架,因为它为每个操作提供内置设施。
我们大多数人可能已经熟悉基于函数的视图,并且知道如何使用基于函数的视图处理请求。
在本教程中,我们将介绍基于类的通用视图。这些是一组高级内置视图,用于实现选择性 CRUD(创建、检索、更新和删除)操作。使用基于类的视图,我们可以轻松处理视图的 GET、POST 请求。
它们并不能替代基于函数的视图,而是在基于函数的视图之上提供一些额外的功能。
让我们简要概述一下基于函数的视图和基于类的视图。

基于函数的视图

基于函数的视图适合初学者;初学者很容易理解它们。与基于类的视图相比,它很容易理解。
  • 它易于理解且易于使用。

  • 它提供了显式的代码流程。

  • 直接使用装饰器。

但基于函数的视图无法扩展,并且还会导致代码冗余。

基于类的视图

基于类的视图可以用来代替基于函数的视图。所有操作都使用 Python 对象而不是函数进行处理。它们提供了一些关于基于函数的视图的优秀示例。基于类的视图可以轻松地实现CRUD操作。
  • 它遵循 Django 的 DRY 约定。

  • 我们可以使用 Mixin 扩展基于类的视图,并根据需求添加更多功能。

  • 它允许继承另一个类,可以针对各种用例进行修改。

但这些内容理解起来很复杂,也很难阅读。它具有隐式代码流。

专属福利 

👉点击领取:最全Python资料合集

使用基于类的视图执行 CRUD(创建、检索、更新、删除)

我们将演示如何使用基于类的视图创建基本的 CRUD 应用程序。
我们将创建名为Hello 的项目,其中包含一个名为exampleapp 的应用程序。
在应用程序中,我们将在model.py文件中创建一个 Employee 模型。
例子 -
from django.db import models  # Create your models here.  class Employee(models.Model):      first_name = models.CharField(max_length=30)      last_name = models.CharField(max_length=30)      mobile = models.CharField(max_length=10)      email = models.EmailField()      def __str__(self):          return "%s %s" % (self.first_name, self.last_name)
然后我们运行以下命令。
python manage.py makemigrationspython manage.py migrate
现在,我们将在 form.py 文件中为此模型创建 Django ModelForm 。它将用于向模板显示表单。
froms.py
from django.forms import fields  from .models import Employee  from django import forms  class EmployeeForm(forms.ModelForm):      class Meta:          # To specify the model to be used to create form          model = Employee          # It includes all the fields of model          fields = '__all__'  

实现基于类的视图

基于函数的视图通过不同的类实例方法返回不同的 HTTP 请求方法。所以基于函数的将如下所示。
from django.http import HttpResponse  def function_view(request):      if request.method == 'GET':          # View logic will place here          return HttpResponse('response')
如果我们实现基于类的视图,它将如下所示。
from django.http import HttpResponse  from django.views import View  class NewView(View):      def get(self, request):          # View logic will place here          return HttpResponse('response')
要处理基于类的视图,我们需要使用urls.py 文件中的as_view() 。
# urls.py  from django.urls import path  from myapp.views import NewView  urlpatterns = [      path('about/', NewView.as_view()),  ]

创建视图

CreateView 实现视图以在数据库中创建表的实例。该视图自动执行创建实例的所有操作。我们只需要指定模型名称即可创建视图及其字段。基于类的创建视图将搜索employee_form.html。让我们看看下面创建视图的示例。
注意 - employee_form.html 文件应包含在 template/app_name/employee_form.html 中。在我们的示例中,文件位置是 template/sampleapp/employee_form.html。
View.py
from .models import Employee  from .forms import EmployeeForm  from django.views.generic.edit import CreateView  class EmployeeCreate(CreateView):      model = Employee      fields = '__all__'  
urls.py
from django.urls import path  from .views import EmployeeCreate  urlpatterns = [      path('', EmployeeCreate.as_view(), name = 'EmployeeCreate')  ]  
现在我们在本地主机上运行服务器。
输出:

Image

在这里,我们得到了可以创建员工的表单。我们来看看创建员工的演示。

Image

正如我们在管理面板中看到的,该员工已在数据库中创建。

Image

检索视图

有两种检索视图 - ListView和DetailView。我们将使用 ListView,它指的是显示数据库中表的多个实例的视图。我们只需要指定应用ListView的模型名称,基于类的ListView将自动为我们完成这项工作。要检索数据,我们需要创建app_name/modelname_list.html文件。
views.py
from django.views.generic.list import ListView  class EmployeeRetrieve(ListView):      model = Employee  
url.py
from django.urls import path  from .views import EmployeeCreate, EmployeeRetrieve  urlpatterns = [      path('', EmployeeCreate.as_view(), name = 'EmployeeCreate'),      path('retrieve/', EmployeeRetrieve.as_view(), name = 'EmployeeRetrieve')  ]  
示例应用程序/模板/employee_list.html
{% extends 'base.html' %}  {% block content %}      <ul class="nav flex-column">          <!-- Iterate over object_list -->          {% for object in object_list %}          <!-- Display Objects -->          <li class="nav-item">First Name: {{ object.first_name }}</li>          <li class="nav-item">Last Name: {{ object.last_name }}</li>          <li class="nav-item">Mobile: {{ object.mobile }}</li>          <li class="nav-item"> Email: {{ object.email }}</li>          <hr/>          <!-- If object_list is empty -->          {% empty %}          <li class="nav-item">No objects Find</li>          {% endfor %}      </ul>  {% endblock content %}  
现在,我们运行本地主机服务器并发送请求以获取数据。

Image

详细视图

DetailView与 ListView 不同,因为它显示数据库中表的一个实例。Django自动为每个条目分配一个主键,我们需要在请求中指定<pk> 。DetailView 将自动执行所有操作。DetailView的实现与ListView相同,我们需要创建modelname_detail.html。
我们来了解一下DetailView的以下实现。
View.py
from django.views.generic.detail import DetailView  class EmployeeDetail(DetailView):      model = Employee  
url.py
from django.urls import path  from .views import EmployeeCreate, EmployeeDetail, EmployeeRetrieve  urlpatterns = [      path('', EmployeeCreate.as_view(), name = 'EmployeeCreate'),      path('retrieve/', EmployeeRetrieve.as_view(), name = 'EmployeeRetrieve'),      path('retrieve/<int:pk>', EmployeeDetail.as_view(), name = 'EmployeeDetail')  ]  
示例应用程序/模板/employee_detail.html
{% extends 'base.html' %}  {% block content %}      <h1>{{ object.first_name }} {{object.last_name}}</h1>      <p>{{ object.email }}</p>      <p>{{ object.mobile }}</p>  {% endblock content %}  
我们创建了一名新员工,并将 2 作为主键。运行服务器并为请求提供主键。
输出:

Image

更新视图

UpdateView允许使用更多详细信息从数据库更新表的特定实例。该视图用于更改数据库中的条目。例如,我们要更改用户的名字。我们需要指定模型名称,它会自动完成所有操作。让我们看看下面的UpdateView的实现。
我们已经在模板中创建了employee_form .html 文件。在我们的例子中,它是D:\python_project\Myfirstdjangoproject\hello\template\employee_form.html>
View.py
from django.views.generic.edit import UpdateView  class EmployeeUpdate(UpdateView):      model = Employee  
网址.py
from django.urls import path  from .views import EmployeeCreate, EmployeeDetail, EmployeeRetrieve, EmployeeUpdate, EmployeeDelete  urlpatterns = [      path('', EmployeeCreate.as_view(), name = 'EmployeeCreate'),      path('retrieve/', EmployeeRetrieve.as_view(), name = 'EmployeeRetrieve'),      path('<int:pk>', EmployeeDetail.as_view(), name = 'EmployeeDetail'),      path('<int:pk>/update/', EmployeeUpdate.as_view(), name = 'EmployeeUpdate'),      path('<int:pk>/delete/', EmployeeDelete.as_view(), name = 'EmployeeDelete')  ]  
输出:

Image

我们更新了对象的姓氏。更新后的值将自动添加到数据库中。

Image

删除视图

DeleteView 允许从数据库中删除表的实例。它用于删除数据库中的条目。
我们只需要指定模型名称,它就会自动完成所有操作。让我们看看下面的UpdateView的实现。
view.py
from django.views.generic.edit DeleteView  class EmployeeDelete(DeleteView):      model = Employee      # here we can specify the URL       # to redirect after successful deletion      success_url = '/'  
现在,我们创建 URL 路径来映射视图。
url.py
from django.urls import path  from .views import EmployeeCreate, EmployeeDetail, EmployeeRetrieve, EmployeeUpdate, EmployeeDelete  urlpatterns = [      path('', EmployeeCreate.as_view(), name = 'EmployeeCreate'),      path('retrieve/', EmployeeRetrieve.as_view(), name = 'EmployeeRetrieve'),      path('<int:pk>', EmployeeDetail.as_view(), name = 'EmployeeDetail'),      path('<pk>/update/', EmployeeUpdate, name = 'EmployeeUpdate'),      path('<pk>/delete/', EmployeeDelete, name = 'EmployeeDelete')  ]  
现在,我们创建template/sampleapp/employee_confirm_delete.html。
{% extends 'base.html' %}  {% block content %}      <form method="post">  {% csrf_token %}      <p>Are you sure you want to delete "{{ object }}"?</p>      <input type="submit" value="Confirm">  </form>  {% endblock content %}  
输出:

Image

当我们点击确认按钮时,该对象将被删除并重定向到主页。
我们使用类创建了 CRUD 操作

代码

下面是基于类的通用视图的完整代码。
View.py
from django.shortcuts import redirect, render  from django.urls import reverse, reverse_lazy  from django.contrib import messages  from .models import Employee  from .forms import EmployeeForm  from django.views.generic.edit import CreateView, DeleteView, UpdateView  from django.views.generic.list import ListView  from django.views.generic.detail import DetailView  class EmployeeCreate(CreateView):      model = Employee      fields = '__all__'      success_url = reverse_lazy('sampleapp: EmployeeRetrieve')  class EmployeeRetrieve(ListView):      model = Employee      success_url = reverse_lazy('sampleapp: EmployeeRetrieve')  class EmployeeDetail(DetailView):      model = Employee      success_url = reverse_lazy('sampleapp: EmployeeRetrieve')  class EmployeeUpdate(UpdateView):      model = Employee      template_name_suffix = '_update_form'      fields = '__all__'      success_url = reverse_lazy('sampleapp: EmployeeRetrieve')      # def get_success_url(self):  class EmployeeDelete(DeleteView):      model = Employee      # here we can specify the URL       # to redirect after successful deletion      success_url = '/'  
Hello/urls.py
"""Hello URL Configuration  The `urlpatterns` list routes URLs to views. For more information please see:      https://docs.djangoproject.com/en/3.1/topics/http/urls/  Examples:  Function views      1. Add an import:  from my_app import views      2. Add a URL to urlpatterns:  path('', views.home, name='home')  Class-based views      1. Add an import:  from other_app.views import Home      2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')  Including another URLconf      1. Import the include() function: from django.urls import include, path      2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))  """  from django.contrib import admin  from django.urls import path  from django.urls.conf import include  urlpatterns = [      path('admin/', admin.site.urls),      path('', include(('sampleapp.urls'), namespace='sampleapp')) ]  
sampleapp/url.py
from django.urls import path  from .views import EmployeeCreate, EmployeeDetail, EmployeeRetrieve, EmployeeUpdate, EmployeeDelete  app_name = 'sampleapp'  urlpatterns = [      path('', EmployeeCreate.as_view(), name = 'EmployeeCreate'),      path('retrieve/', EmployeeRetrieve.as_view(), name = 'EmployeeRetrieve'),      path('<int:pk>', EmployeeDetail.as_view(), name = 'EmployeeDetail'),      path('<int:pk>/update/', EmployeeUpdate.as_view(), name = 'EmployeeUpdate'),      path('<int:pk>/delete/', EmployeeDelete.as_view(), name = 'EmployeeDelete')  ]  
template/base.html
<!doctype html>  <html lang="en">    <head>      <!-- Required meta tags -->      <meta charset="utf-8">      <meta name="viewport" content="width=device-width, initial-scale=1">      <!-- Bootstrap CSS -->      <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">      <title>Register Page</title>    </head>    <body>    <div class = 'col-md-8'>       {% if messages %}          <ul>               {% for message in messages %}                <div class = 'alert alert-{{message.tags}}'>                  {{ message }}                 </div>                {% endfor %}          </ul>       {% endif %}     </div>    {% block content %}      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>      {% endblock content %}    </body>  </html>  
template/sampleapp/employe_list
{% extends 'base.html' %}  {% block content %}  <table class="table table-borderless">      <thead class="border-bottom font-weight-bold">          <tr>              <td>First Name</td>              <td>Last Name</td>              <td>Mobile</td>              <td>Email</td>                  {% comment %} <a href="{% url 'EmployeeRetrieve' %}" class="btn btn-outline-success">                      <i class="fas fa-plus"></i> Add New {% endcomment %}                  </a>              </td>          </tr>      </thead>      {% for object in object_list %}          <!-- Display Objects -->          <tr>                  <td>{{ object.first_name }}</td>                  <td> {{object.last_name }}</td>                  <td> {{object.mobile }}</td>                  <td>{{object.email }} </td>              <td>              <td><button><a href = '/{{object.pk}}/delete' class = 'class="btn text-secondary px-0'> Delete              </a></button></td>              <td><button><a href = '/{{object.pk}}/update' class = 'class="btn text-secondary px-0'> Update              </a></button></td>      {% endfor %}  </table>  
template/sampleapp/employe_detail
{% extends 'base.html' %}  {% block content %}      <h1>{{ object.first_name }} {{object.last_name}}</h1>      <p>{{ object.email }}</p>      <p>{{ object.mobile }}</p>      <td><button><a href = '/{{object.pk}}/delete' class = 'class="btn text-secondary px-0'> Delete      </a></button></td>      <td><button><a href = '/{{object.pk}}/update' class = 'class="btn text-secondary px-0'> Update    </a></button></td>  {% endblock content %}  
template/sampleapp/employe_update_form.html
{% extends 'base.html' %}  {% block content %}      <form method="post">      {% csrf_token %}          {{ form.as_p }}          <input type="submit" value="Update">      </form>  {% endblock content %}  
template/sampleapp/employe_confirm_delete.html
{% extends 'base.html' %}  {% block content %}      <form method="post">{% csrf_token %}      <p>Are you sure you want to delete "{{ object }}"?</p>      <input type="submit" value="Confirm">  </form>  {% endblock content %}  

结论

在本教程中,我们讨论了基于类的视图以及它们与基于函数的视图有何不同。我们已经使用内置视图实现了增删改查操作。
CBV 是从现有视图继承并覆盖属性(template_name)或方法的强大方法。
这些视图已经预先编写了代码,因此我们不需要进行硬编码。但不建议初学者这样做,因为这无助于理解 Django 的核心深度。一旦您熟悉了基于函数的视图的概念。您可以转向基于阶级的观点
Image
 1
Image
热门推荐

Image