Diango教程-基于 Django 类的通用视图
Django 是最流行的 Python Web 框架,用于快速 Web 应用程序开发。它提供了一个内置界面,可以轻松使用它。它也被称为包含电池的框架,因为它为每个操作提供内置设施。
我们大多数人可能已经熟悉基于函数的视图,并且知道如何使用基于函数的视图处理请求。
在本教程中,我们将介绍基于类的通用视图。这些是一组高级内置视图,用于实现选择性 CRUD(创建、检索、更新和删除)操作。使用基于类的视图,我们可以轻松处理视图的 GET、POST 请求。
它们并不能替代基于函数的视图,而是在基于函数的视图之上提供一些额外的功能。
让我们简要概述一下基于函数的视图和基于类的视图。
基于函数的视图
基于函数的视图适合初学者;初学者很容易理解它们。与基于类的视图相比,它很容易理解。
- 它易于理解且易于使用。
- 它提供了显式的代码流程。
- 直接使用装饰器。
但基于函数的视图无法扩展,并且还会导致代码冗余。
基于类的视图
基于类的视图可以用来代替基于函数的视图。所有操作都使用 Python 对象而不是函数进行处理。它们提供了一些关于基于函数的视图的优秀示例。基于类的视图可以轻松地实现CRUD操作。
- 它遵循 Django 的 DRY 约定。
- 我们可以使用 Mixin 扩展基于类的视图,并根据需求添加更多功能。
- 它允许继承另一个类,可以针对各种用例进行修改。
但这些内容理解起来很复杂,也很难阅读。它具有隐式代码流。
使用基于类的视图执行 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 makemigrations
python 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')
]
现在我们在本地主机上运行服务器。
输出:
在这里,我们得到了可以创建员工的表单。我们来看看创建员工的演示。
正如我们在管理面板中看到的,该员工已在数据库中创建。
检索视图
有两种检索视图 - 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 %}
现在,我们运行本地主机服务器并发送请求以获取数据。
详细视图
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 作为主键。运行服务器并为请求提供主键。
输出:
更新视图
UpdateView允许使用更多详细信息从数据库更新表的特定实例。该视图用于更改数据库中的条目。例如,我们要更改用户的名字。我们需要指定模型名称,它会自动完成所有操作。让我们看看下面的UpdateView的实现。
我们已经在模板中创建了employee_form .html 文件。在我们的例子中,它是D:python_projectMyfirstdjangoprojecthellotemplateemployee_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')
]
输出:
我们更新了对象的姓氏。更新后的值将自动添加到数据库中。
删除视图
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 %}
输出:
当我们点击确认按钮时,该对象将被删除并重定向到主页。
我们使用类创建了 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/bootstrap@5.0.2/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/bootstrap@5.0.2/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 的核心深度。一旦您熟悉了基于函数的视图的概念。您可以转向基于阶级的观点。