Django-Vue搭建个人博客:基于类的视图
15526 views, 2021/03/05 updated Go to Comments
传统 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了。
从这个地方就可以看出,序列化器
serializer
不仅可以将数据进行序列化、反序列化,还包含数据验证、错误处理、数据库操作等能力。序列化这个概念与具体语言无关。Python 或 JavaScript 对象转换为 Json 都称为序列化,反之为反序列化。Json 是两种语言传输信息的桥梁,一但信息到达,对方都需要将其还原为自身的数据结构。
由于详情接口需要返回完整的字段数据(与阉割版的文章列表接口不同),所以要重新给它定义一个序列化器:
# 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
除了上述介绍的以外,框架还提供
ListModelMixin
、CreateModelMixin
等混入类或通用视图,覆盖了基础的增删改查需求。