泽恩小站-教程区 Help

基于类的视图

传统 Django 中就有基于类的视图的存在,DRF 中自然也有。优点也都差不多,即实现功能的模块化继承、封装,减少重复代码。接下来就用文章详情接口练练手。

首先在视图中新增下面的代码:

# article/views.py from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status from django.http import Http404 from article.models import Article from article.serializers import ArticleDetailSerializer class ArticleDetail(APIView): """文章详情视图""" def get_object(self, pk): """获取单个文章对象""" try: # pk 即主键,默认状态下就是 id return Article.objects.get(pk=pk) except: raise Http404 def get(self, request, pk): article = self.get_object(pk) serializer = ArticleDetailSerializer(article) # 返回 Json 数据 return Response(serializer.data) def put(self, request, pk): article = self.get_object(pk) serializer = ArticleDetailSerializer(article, data=request.data) # 验证提交的数据是否合法 # 不合法则返回400 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): article = self.get_object(pk) article.delete() # 删除成功后返回204 return Response(status=status.HTTP_204_NO_CONTENT) ...

代码不复杂,就是提供了对文章详情的获取修改删除的 3 个方法,以及 1 个用于获取单个文章 model 的辅助方法。和之前说的一样,DRF 类视图与传统 Django 的区别, .get().put() 就是多了一个将对象序列化(或反序列化)的步骤。 .delete() 方法因为不用返回实际数据,执行完删除动作就OK了。

由于详情接口需要返回完整的字段数据(与阉割版的文章列表接口不同),所以要重新给它定义一个序列化器:

# article/serializers.py ... class ArticleDetailSerializer(serializers.ModelSerializer): class Meta: model = Article fields = '__all__'

fields = '__all__' 代表要使用所有字段。

配置 urls.py

# article/urls.py ... urlpatterns = [ ... path('<int:pk>/', views.ArticleDetail.as_view(), name='detail'), ]

这就可以了。

发送一个请求试试:

# 再次提醒:建议用 Postman 来发送 web 请求 # 教程为了轻便使用了httpie,读者改为Postman即可 > http http://127.0.0.1:8000/api/article/1/ HTTP/1.1 200 OK Allow: GET, PUT, DELETE, HEAD, OPTIONS Content-Length: 141 Content-Type: application/json ... { "body": "Maybe say somthing here...", "created": "2020-06-15T09:24:18Z", "id": 1, "title": "My first post", "updated": "2020-06-15T09:24:38.622789Z" }

再试试修改文章接口:(注意请求方式变成了 PUT

> http PUT http://127.0.0.1:8000/api/article/1/ title=something... body=changed... HTTP/1.1 200 OK ... { "body": "changed...", "created": "2020-06-15T09:24:18Z", "id": 1, "title": "something...", "updated": "2020-07-02T07:05:49.554354Z" }

再试试把它删除掉:

> http DELETE http://127.0.0.1:8000/api/article/1/ HTTP/1.1 204 No Content Allow: GET, PUT, DELETE, HEAD, OPTIONS ...

这篇 id=1 的文章就被删除掉了。

通用视图

对数据的增删改查是几乎每个项目的通用操作,因此可以通过 DRF 提供的 Mixin 类直接集成对应的功能。

修改一下 ArticleDetail 视图:

# article/views.py ... from rest_framework import mixins from rest_framework import generics class ArticleDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): """文章详情视图""" queryset = Article.objects.all() serializer_class = ArticleDetailSerializer 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)

使用 Mixin 已经足够简单了,但我们还可以让它更简单:

# article/views.py ... class ArticleDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Article.objects.all() serializer_class = ArticleDetailSerializer

发送请求试试,功能和最开头那个继承 APIView 的视图是完全相同的。

列表接口也可以做同样的修改:

# article/views.py ... class ArticleList(generics.ListCreateAPIView): queryset = Article.objects.all() serializer_class = ArticleListSerializer
Last modified: 06 January 2025