zoukankan      html  css  js  c++  java
  • Django REST framework 第三章 CBV

    从介绍Django快开始,我们就一直在使用FBV的方式来撰写代码,二者本质上并没有太大的区别,然而到了REST framework,更会倾向于用CBV来写API的视图,后面会看到这个方式的强大,它允许我们重用常用的功能,让代码更简练。

    Rewriting Our API using class-based view

    现在开始撰写一个简单的CBV代码,打开app内的views.py文件

    from rest_framework import status
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from django.http import Http404
    from app01.models import Snippet
    from app01.serializers import SnippetSerializer
    
    
    class SnippetList(APIView):
        """
        列出所有的对象或者创建一个新的对象
        """
        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方法间更好的分离,来更新一下上述实例的代码,还是在app的views.py文件。

    class SnippetDetail(APIView):
        """
        获取、更新、删除一个实例对象
        """
        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)

    这段代码看起来很棒,但是它现在还是跟FBV的代码很像。

    同时,还需要稍微重构app内的urls文件,现在需要用CBV的方式。

    from app01 import views
    from django.urls import path, include
    from rest_framework.urlpatterns import format_suffix_patterns
    
    
    urlpatterns = [
        path('snippets/', views.SnippetList.as_view()),
        path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
    ]
    urlpatterns = format_suffix_patterns(urlpatterns)

    好了,我们已经完成了。如果你将代码允许起来,应该跟之前的效果一样。

    Using mixins

    使用CBV的的最大优点之一就是,它允许我们很容易的编写一些可重用的行为。

    到目前为止,创建、删除、更新、获取这些操作在任何模型支持的API视图中都是非常相似的。

    一起来看下,如何使用mixin类来构建视图。再次修改view.py文件

    from app01.models import Snippet
    from app01.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)

    来花点时间审查一下,到底这里发生了什么。首先创建的类使用了GenericAPIView,同时也继承了ListModelMixinCreateModelMixin

    基类提供了核心的功能,mixin类提供了.list().create()操作。然后,明确的绑定了getpost方法到合适的行为。到目前为止,足够简单。

    继续改造另一个CBV

    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)

    跟上面的CBV非常相似。同样的,我们再一次使用GenericAPIView来提供核心代码,然后使用mixin中的.retrieve(), .update(), .destory()方法。

    Using generic class-based views

    上面使用mixin类使用比之前更少的代码稍微重写了视图,但是我们还能更上一层楼。REST framework提供了一系列已经混合封装好的generic视图,进而可以直接在views.py文件内简化使用。

    from app01.models import Snippet
    from app01.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

    看到这里,不免会惊叹,OMG!这也太简洁了。我们免费得到了大量的代码,我们的代码看起来很好,很干净,很符合语言习惯的Django。

  • 相关阅读:
    前端自动化测试python+webdriver
    JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
    onpageshow 监听页面是否是缓存页面
    CSS完美实现iframe高度自适应(支持跨域)
    HTML5 简单归纳 -- 前端知识 (一)
    JavaScrip 概述 -- 前端知识
    CSS 简单归纳 -- 前端知识
    HTML 简单归纳 -- 前端知识
    解决vscode-insider连接不了远程服务器问题
    回首,只为再出发!
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/9460111.html
Copyright © 2011-2022 走看看