Drf/Django开发记录

Drf官网教程(三) - CBV

2018-06-23  本文已影响54人  dyq666

目录

  1. 将FBV改为CBV
  2. 使用Mixins
  3. 使用generic中更上层的封装类

0. 概述

使用CBV的好处是可以减少代码的重复量。

1. 将FBV改为CBV

大部分代码都没有变动,直接将原来的代码粘到类中,进行一些小的修改即可。

from django.http import Http404
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


class SnippetList(APIView):
    """list, create"""
    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):
    """retrive, update, delete"""
    def get_object(self, pk):
        """根据id获取Model实例"""
        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)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk=pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

...

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

2. 使用Mixins

大部分的view都要完成上面这些固定的代码,因而Drf将这些固定部分放到了mixins中。只要使用GenericAPIView + mixin就能省去这部分。但是要完成下面这两步:

  1. 指明操作的model集合和序列化类
  2. mixins提供的是ACTION(list, retrieve, create, update, destroy),而view的入口是HTTP-METHOD,所以需要手动将这些METHOD与ACTION绑定。
from rest_framework import mixins
from rest_framework.generics import GenericAPIView

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  GenericAPIView):
    """
    get:list 
    post:create
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(self, request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(self, request, *args, **kwargs)


class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    GenericAPIView):
    """
    get:retrieve
    put:update
    delete:destroy
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(self, request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(self, request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(self, request, *args, **kwargs)

3. 使用generic中更上层的封装类

由于大部分的绑定操作也是固定的,所以generics中提供了一些已经绑定过的类。

from rest_framework import generics

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
image.png

如果这些都不满足要求的话,可以模仿这些类,手动定制。
比如定制一个update-put,destroy-delete的类。

class UpdateDestroyAPIView(mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
    """
    Concrete view for updating or deleting a model instance.
    """
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

现在代码变得非常简明了!

上一篇 下一篇

猜你喜欢

热点阅读