zoukankan      html  css  js  c++  java
  • django-rest-framework之基于类的视图

    前言:上一篇博客中,主要讲的是请求和响应,项目里面views.py中的视图函数都是基于函数的,并且我们介绍了@api_view这个很有用的装饰器。同时,我们还介绍了APIView这个类,但是还没使用它。在这篇文章中,我们要做的是把基于方法的视图改为基于类的视图,这是很强大的模式,使我们可以重用常用功能,可以减少代码量。

    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请求分离开变成单个的方法,而不是if...elif...这样的结构,所以这样处理起来很更加的高效。同样的,把另一个视图函数也进行修改:

    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)

    That's looking good. Again, it's still pretty similar to the function based view right now.

    We'll also need to refactor our urls.py slightly now that we're using class-based views.

    from django.conf.urls import url
    from rest_framework.urlpatterns import format_suffix_patterns
    from snippets import views
    
    urlpatterns = [
        url(r'^snippets/$', views.SnippetList.as_view()),
        url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
    ]
    
    urlpatterns = format_suffix_patterns(urlpatterns)

    这样就可以运行程序了,功能和之前的是一样的。以上,我觉得根本一点点难度都没有……

    使用mixin

    使用基于类的视图的一个重大胜利是它允许我们轻松地构造可重复使用的行为

    到目前为止,我们使用的创建/检索/更新/删除操作对于我们创建的任何模型支持的API视图将非常相似。这些常见的行为是在REST框架的mixin类中实现的

    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)

    新的视图类中继承了 generic.GenericAPIView、mixins.ListModelMixin和mixins.CreatteModelMixin,类的作用看字面意思就能懂啦,mixins类为我们提供了list()和create()方法,当然,使用这两个函数需要先设置queryset和serializer_class,这点我们查看一下mixins的源码就可以看出来了,比如list方法:

    class ListModelMixin(object):
        """
        List a queryset.
        """
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)

    同理,修改一下另一个视图类:

    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)

    使用通用的视图类

    到这里,视图代码已经简化了许多了,但是我要告诉你的是,还可以进一步简化。。。在此,让我们一起在心中默念:

    人生苦短,我用Python

    进一步简化就是连mixins类都不用了,只使用generics就可以了,代码如下:

    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

    Wow, that's pretty concise. We've gotten a huge amount for free, and our code looks like good, clean, idiomatic Django.

    来张效果图,效果与与之前并不区别,只能用类方法写视图,减少了不少代码,逼格更高了:

  • 相关阅读:
    datetimepicker 日期值显示不完全(点击按钮后)
    南昌旋风科技有限公司的评价很烂,擅自修改dns域名解析。也不通知客户,导致34天无法解析。
    2009年树种铁树种子,每个特价3元一个!
    asp.net c# 如何读取XML文件里的CDATA里的HTML
    招商银行开始抢钱了,月管理费5元。2009年7月开始,杭州的招行是这样的。准备注销账号了
    圆通快递服务台太恶劣了,强烈要求抵制圆通快递。
    asp.net c#里如何使用 varchar(max) 参数
    MasterPage 和 page 事件顺序
    window7 安装 Microsoft SQL Server 2008 Enterprise Edition 需要注意的问题
    探讨下Tag标签的数据库设计(千万级数据量)
  • 原文地址:https://www.cnblogs.com/0zcl/p/7788574.html
Copyright © 2011-2022 走看看