教程3--基于类的视图

教程3–基于类的视图

本人英语巨渣,文章都是瞎翻译的,如有雷同,纯属巧合~

除了使用基于函数的视图,我们也可以使用基于类的视图。由于类视图的可复用性,我们可以缩减很多代码,这也体现了DRY原则。
这一篇主要内容就是改写之前的写的视图,各种花式改编,最后你就会发现,原来一个基于模型的视图类原来可以寥寥几行代码就搞定了。

使用基于类的视图重写之前的案例

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)


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, 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)

相对应的urls.py也需要修改一下才行:

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'^snippet/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view())
]

urlpatterns = format_suffix_patterns(urlpatterns)

从上面的例子看,似乎改写成基于类的视图以后,程序也没有多大的改变,基于类的视图真有那么好吗?别急,下面就让基于类的视图发挥威力。

使用mixin

使用基于类的视图一个最大的优势就是可以让我们简单地组合可重用的行为来完成复杂的动作。
不知大家有没有发现,我们在上述例子中一直在写的create/retrieve/update/delete这些行为,其实不管对于那种模型,需要完成的行为都是差不多的。那么这些行为就可以说是公共行为了。这些公共行为被REST框架实现成了一个个的mixin。
让我们来看一看如何使用mixin来改写之前的案例:

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)


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)

是不是感觉简单多了?mixin帮我们做了大部分的操作。我们已经不用自己写逻辑去操作serializer了~
然而,貌似这里每个方法都是直接调用了mixin的方法而已,这样的话我们为什么不封装一个通用一点的视图出来?
放心,REST早就想到了。

使用通用视图

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

对比一下前后程序的代码量,感受类视图的魅力吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值