django-restframework之间的各种view之间的关系以及使用

1.api_view和APIView

首先api_view和APIView对应了最基本的FBV和CBV,api_view是一个装饰器用来确保视图中收到request实例,并且将上下文添加到相应中,而在drf中写CBV最先要继承的就是APIView,可以通过代码示例来掌握两者的使用的区别

from .serializers import SnippetsSerializer
from .models import  Snippet

@api_view(["GET",])
def snippets_list(request):
    snippets=Snippet.objects.all()
    snippets_serializer=SnippetsSerializer(snippets,many=True)
    return Response(snippets_serializer.data,status=status.HTTP_200_OK)

@api_view(["GET","PUT","DELETE"])
def snippet_detail(request,pk):
    try:
        snippet=Snippet.objects.get(id=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_400_BAD_REQUEST)
    if request.method=="GET":
        snippet_serializer=SnippetsSerializer(snippet)
        return Response(snippet_serializer.data,status=status.HTTP_200_OK)
    if request.method=="PUT":
        snippet_serializer=SnippetsSerializer(snippet,request.data)
        if snippet_serializer.is_valid():
            snippet_serializer.save()
            return Response(snippet_serializer.data,status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)
    if request.method=="DELETE":
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 其中api_view中填入的是fbv的请求方法,如果未传入参数默认使用的是GET方法

CBV的基本用法如下

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)

从上所看,drf中fbv和cbv的写法同django本身的写法大同小异,只是使用的装饰器和继承的类不同。

2.高级组合

当然drf作为一个成熟的框架其功能远远不止如此,drf的最终目标还是通过最少的代码实现原来一样的功能,使用CBV的一大好处就是我们可以轻松的可重用的行为,我们可以看看如何进一步优化我们的代码

from snippets.models import Snippet
from snippets.serializers import SnippetsSerializer
from rest_framework import mixins
from rest_framework import generics

class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetsSerializer

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

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

我们在此引入了mixins和generics模块,我们可以看出上面的代码同样实现get和post方法,但是我们在get和post方法内部并没有去实现过于繁杂的代码,仅仅是调用了一个list和post方法,这样我们就可以将相应的http请求定到对应的操作上,如get请求就对应了list方法而post请求就对应了create方法。我们在这个CBV中只需要指明我们需要使用的对象查询集合和serializer类。我们可以看看list和create的内部实现原理

    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)
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

可以看出在list方法内部跟我们在第一部分实现的get方法大致相同,首先获取我们在类中执行的queryset和serializer,最后将对象序列化。至于GenericAPIView它继承的是我们先前使用APIView.
虽然到了这里我们的代码已经足够精简但是还是可以进一步优化,如下。

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


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetsSerializer

我们这里使用的是ListCreateAPIView,我们可以看下其内部源码

class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
    """
    Concrete view for listing a queryset or creating a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

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

我们可以看到其内部自动的将http请求方法对应到我们的对象操作方法上,至此我们只需要在CBV中指明queryset和serializer_class即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值