基于类的视图——Django Rest Framework
基于类的视图有助于组成可重用的行为位。 Django REST Framework 提供了几个预构建的视图,允许我们重用通用功能并保持代码干燥。在本节中,我们将深入研究 Django REST Framework 中不同的基于类的视图。
This article assumes you are already familiar with Django and Django REST Framework.
Checkout –
- Django tutorial
- Create a basic API using Django Rest Framework
接口视图
APIView 类为标准列表和详细信息视图提供了通常需要的行为。使用 APIView 类,我们可以将根视图重写为基于类的视图。它们提供诸如 get()、post()、put()、patch() 和 delete() 等操作方法,而不是定义处理程序方法。
使用 APIView 创建视图
我们来看看如何使用 APIView 创建视图。 views.py 文件模块如下:
Python3
from django.shortcuts import render
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(APIView):
"""
List all Transformers, or create a new Transformer
"""
def get(self, request, format=None):
transformers = Transformer.objects.all()
serializer = TransformerSerializer(transformers, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = TransformerSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,
status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class TransformerDetail(APIView):
"""
Retrieve, update or delete a transformer instance
"""
def get_object(self, pk):
# Returns an object instance that should
# be used for detail views.
try:
return Transformer.objects.get(pk=pk)
except Transformer.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
transformer = self.get_object(pk)
serializer = TransformerSerializer(transformer)
return Response(serializer.data)
def put(self, request, pk, format=None):
transformer = self.get_object(pk)
serializer = TransformerSerializer(transformer, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, pk, format=None):
transformer = self.get_object(pk)
serializer = TransformerSerializer(transformer,
data=request.data,
partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
transformer = self.get_object(pk)
transformer.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Python3
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from transformers import views
urlpatterns = [
path('transformers/', views.TransformerList.as_view()),
path('transformers//', views.TransformerDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Python3
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('transformers.urls')),
]
Python3
from rest_framework import mixins
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class TransformerDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
Python3
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(generics.ListCreateAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
class TransformerDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
代码类似于常规的 Django 视图,但不同 HTTP 方法之间有更好的分离。
- get() 方法处理 HTTP GET 请求
- post() 方法处理 HTTP POST 请求
- put() 方法处理 HTTP PUT 请求
- patch() 方法处理 HTTP PATCH 请求
- delete() 方法处理 HTTP DELETE 请求
设置 URL 配置
由于我们使用基于类的视图,因此我们在 urls.py 文件路径中提及视图的方式略有不同。在 app (transformers) 文件夹中创建一个名为 urls.py 的新文件(如果不存在)并添加以下代码
蟒蛇3
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from transformers import views
urlpatterns = [
path('transformers/', views.TransformerList.as_view()),
path('transformers//', views.TransformerDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
接下来,设置根 URL 配置。您可以打开urls.py(settings.py文件所在的文件夹)并添加以下代码
蟒蛇3
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('transformers.urls')),
]
编写和发送 HTTP 请求
1. 创建一个新条目——
HTTPie 命令是:
http POST :8000/transformers/ name=”Optimus Prime” alternate_mode=”1979 Freightliner Semi” description=”Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader” alive=”True”
输出
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 194
Content-Type: application/json
Date: Sat, 23 Jan 2021 03:48:46 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
"id": 1,
"name": "Optimus Prime"
}
分享命令提示符截图供您参考:
2. 检索现有条目
擎天柱的pk值是1,让我们传递pk值并检索详情
HTTPie 命令是:
http GET :8000/transformers/1/
输出
HTTP/1.1 200 OK
Allow: GET, HEAD, OPTIONS
Content-Length: 194
Content-Type: application/json
Date: Sat, 23 Jan 2021 03:50:42 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
"id": 1,
"name": "Optimus Prime"
}
分享命令提示符截图供大家参考
3. 更新现有条目
让我们通过将其设置为 False 来更新名为 alive 的字段。 HTTPie 命令是:
http PUT :8000/transformers/1/ name=”Optimus Prime” alternate_mode=”1979 Freightliner Semi” description=”Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader” alive=”False”
输出
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 195
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:22:30 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": false,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
"id": 1,
"name": "Optimus Prime"
}
分享命令提示符截图供大家参考
4. 部分更新现有条目
让我们部分更新名为 description 的字段。 HTTPie 命令是:
http PATCH :8000/transformers/1/ description=”Optimus Prime is the strongest and most courageous and leader of all Autobots”
输出
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 181
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:32:40 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": false,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous and leader of all Autobots",
"id": 1,
"name": "Optimus Prime"
}
分享命令提示符截图
5. 删除现有条目
我们将创建一个新条目并将其删除。让我们使用以下 HTTPie 命令创建一个“测试”条目:
http POST :8000/transformers/ name=”Test”
输出
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 77
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:34:41 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": false,
"alternate_mode": null,
"description": null,
"id": 2,
"name": "Test"
}
现在让我们删除“测试”条目(pk = 2)。删除条目的 HTTPie 命令是
http DELETE :8000/transformers/2/
输出
HTTP/1.1 204 No Content
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 0
Date: Sat, 23 Jan 2021 04:35:06 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
分享命令提示符截图
混合
Mixin 类允许我们组合可重用的行为。它们可以从 rest_framework.mixins 导入。让我们讨论不同类型的 mixin 类
- ListModelMixin :它提供了一个.list(request, *args, **kwargs)方法来列出查询集。如果查询集已填充,则响应正文将具有200 OK响应,其中包含查询集的序列化表示。
- CreateModelMixin :它提供了一个.create(request, *args, **kwargs)方法来创建和保存新的模型实例。如果创建了对象,则响应正文具有201 Created响应,并带有对象的序列化表示。如果无效,它会返回带有错误详细信息的400 Bad Request响应。
- RetrieveModelMixin :它提供了一个.retrieve(request, *args, **kwargs)方法,用于在响应中返回现有模型实例。如果可以检索到对象,则响应正文具有200 OK响应,并带有对象的序列化表示。否则,它将返回404 Not Found 。
- UpdateModelMixin :它提供了一个.update(request, *args, **kwargs)方法来更新和保存现有的模型实例。它还提供了一个.partial_update(request, *args, **kwargs)方法用于部分更新和现有模型实例。 .如果对象被更新,响应正文有一个200 OK响应,带有对象的序列化表示。否则,将返回带有错误详细信息的 400 Bad Request 响应。
- DestroyModelMixin :它提供了一个.destroy(request, *args, **kwargs)方法来删除现有的模型实例。如果对象被删除,则响应正文有204 No Content响应,否则将返回404 Not Found 。
Note: We will be using GenericAPIView to build our views and adding in Mixins.
使用 Mixin 创建视图
让我们来看看如何使用 Mixin 类。 views.py 文件模块如下:
蟒蛇3
from rest_framework import mixins
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class TransformerDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
在这里,GenericAPIView 类提供了核心功能,我们正在向它添加 mixin 类。 queryset和serializer_class是 GenericAPIView 类的基本属性。 queryset 属性用于从该视图返回对象,serializer_class 属性用于验证、反序列化输入和序列化输出。
在 TransformerList 类中,我们使用提供 .list() 和 .create() 操作的 mixin 类并将这些操作绑定到 get() 和 post() 方法。在 TransformerDetail 类中,我们使用提供 .retrieve()、.update()、.partial_update() 和 . destroy() 操作并将操作绑定到 get()、put()、patch() 和 delete() 方法。
编写和发送 HTTP 请求
1.新建一个条目
HTTPie 命令是
http POST :8000/transformers/ name=”Bumblebee” alternate_mode=”1979 VW Beetle” description=”Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy” alive=”True”
输出
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 161
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:58:26 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 VW Beetle",
"description": "Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy",
"id": 3,
"name": "Bumblebee"
}
2. 检索所有条目
HTTPie 命令是
http GET :8000/transformers/
输出
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 345
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:59:42 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
[
{
"alive": true,
"alternate_mode": "1979 VW Beetle",
"description": "Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy",
"id": 3,
"name": "Bumblebee"
},
{
"alive": false,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous and leader of all Autobots",
"id": 1,
"name": "Optimus Prime"
}
]
分享命令提示符截图供大家参考
基于类的通用视图
为了使用基于类的通用视图,视图类应该从rest_framework.generics 导入。
- CreateAPIView :它提供了一个 post 方法处理程序,用于仅创建端点。 CreateAPIView 扩展了 GenericAPIView 和 CreateModelMixin
- ListAPIView :它提供了一个 get 方法处理程序,用于只读端点来表示模型实例的集合。 ListAPIView 扩展了 GenericAPIView 和 ListModelMixin。
- RetrieveAPIView :它提供了一个 get 方法处理程序,用于只读端点来表示单个模型实例。 RetrieveAPIView 扩展了 GenericAPIView 和 RetrieveModelMixin。
- DestroyAPIView :它提供了一个删除方法处理程序,用于单个模型实例的仅删除端点。 DestroyAPIView 扩展了 GenericAPIView 和 DestroyModelMixin。
- UpdateAPIView :它提供 put 和 patch 方法处理程序,用于单个模型实例的仅更新端点。 UpdateAPIView 扩展了 GenericAPIView 和 UpdateModelMixin。
- ListCreateAPIView :它提供了 get 和 post 方法处理程序,用于读写端点来表示模型实例的集合。 ListCreateAPIView 扩展了 GenericAPIView、ListModelMixin 和 CreateModelMixin..
- RetrieveUpdateAPIView :它提供了 get、put 和 patch 方法处理程序。它用于读取或更新端点以表示单个模型实例。 RetrieveUpdateAPIView 扩展了 GenericAPIView、RetrieveModelMixin 和 UpdateModelMixin。
- RetrieveDestroyAPIView :它提供 get 和 delete 方法处理程序,用于读取或删除端点以表示单个模型实例。 RetrieveDestroyAPIView 扩展了 GenericAPIView、RetrieveModelMixin 和 DestroyModelMixin。
- RetrieveUpdateDestroyAPIView :它提供了 get、put、patch 和 delete 方法处理程序。它用于读写删除端点以表示单个模型实例。它扩展了 GenericAPIView、RetrieveModelMixin、UpdateModelMixin 和 DestroyModelMixin。
使用基于类的通用视图创建视图
让我们来看看如何使用 Mixin 类。这里我们将利用 ListCreateAPIView 和 RetrieveUpdateDestroyAPIView。 views.py 文件模块如下:
蟒蛇3
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(generics.ListCreateAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
class TransformerDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
您会注意到我们能够避免大量样板代码。这些通用视图结合了来自 mixin 类的可重用行为。我们来看一下 ListCreateAPIView 和 RetrieveUpdateDestroyAPIView 的声明:
class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
......
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
......
编写和发送 HTTP 请求
1.新建一个条目
HTTPie 命令是
http POST :8000/transformers/ name=”Cliffjumper” alternate_mode=”1979 Porsche 924″ description=”His eagerness and daring have no equal” alive=”True”
输出
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 133
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:28:45 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Porsche 924",
"description": "His eagerness and daring have no equal",
"id": 5,
"name": "Cliffjumper"
}
分享命令提示符截图供大家参考
2. 更新现有条目
HTTPie 命令是
http PUT :8000/transformers/5/ name=”Cliffjumper” alternate_mode=”1979 Porsche 924″ description=”Eager and Daring” alive=”True”
输出
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 111
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:35:39 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Porsche 924",
"description": "Eager and Daring",
"id": 5,
"name": "Cliffjumper"
}
分享命令提示符截图供大家参考
3.部分更新现有条目
http PATCH :8000/transformers/3/ alive=”True”
输出
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 151
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:37:54 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 VW Beetle",
"description": "Small, eager, and brave. Acts as a messenger, scout, and spy",
"id": 3,
"name": "Bumblebee"
}
分享命令提示符截图供大家参考
在本节中,我们探索了 Django REST 框架提供的不同类型的基于类的视图。我们使用 APIView 实现了视图并解释了不同类型的 mixin 类。最后,我们展示了各种类型的基于类的通用视图,并演示了它们如何避免大量样板代码。