我们也可以写类视图,而不是方法视图。我们将看到一个强大的模式,该模式允许我们复用公共功能,并且保持代码的DRY(Don’t repeat yourself)。

使用基于类的视图重新我们的API

使用类视图重构views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(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)

目前看来还不错。感觉跟之前的例子很像,但是我们现在把两种不同的HTTP方法分成两个函数了。我们继续重构单个代码片段的视图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.data)
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):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

看起来跟之前差不多。
继续,我们还要重构我们的snippets/urls.py

1
2
3
4
5
6
7
8
9
10
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path('snippets/', views.SnippetList.as_view()),
path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)

Okay,完成了。现在启动服务器,一切还是跟原来一样

使用mixins

使用类视图最大的好处之一就是我们可以轻松地编写可复用的行为。

REST framework的mixin类实现了常用的创建/检索/更新/删除操作。

看一下如何使用mixin类编写视图。这儿还是views.py模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
class SnippetList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

我们的视图继承了GenericAPIViewListModelMixinCreateModelMixin

这些基类提供了核心的功能,mixin类还提供了.list().create()行为。我们将getpost方法绑定合适的行文上。多么简单!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class SnippetDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
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 delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)

我们再次使用GenericAPIView类来提供一些核心功能,并且添加mixins来提供.retrieve().update()。destroy()行为。

使用通用的基于类的视图

使用mixin类可以使我们的视图代码更简洁,但我们可以更进一步,REST framework提供了一系列混合过的通用类,使得我们的views.py模块更加简洁!

1
2
3
4
5
6
7
8
9
10
11
12
13
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer

天啊!太简洁了!我们根本不用做什么!

接下来我们移步教程4,下一节将介绍如何处理API认证和权限的问题。

留言

⬆︎TOP