(二) DRF 视图

DRF中的Request

在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等。

比如,区别于Django中的request从request.GET中获取URL参数,从request.POST中取某些情况下的POST数据。

在APIView中封装的request,就实现了请求数据的解析:

一般来说,GET请求的参数,通过request.query_params来获取。POST、PUT通过request.data来获取

APIView与View的区别

APIView是View的子类
传递给请求处理程序的request实例是REST框架的请求实例,而不是Django的HttpRequest实例

处理程序返回的基于REST框架的Response,而不是Django的HttpResponse,视图函数将会管理内容协商,然后设置正确的渲染方式

任何APIException将会被捕捉,然后转换成合适的response对象

接收到的请求首先被认证,然后赋予相应的权限,然后通过节流器分发给相应的请求处理函数,类似.get()和.post() 

APIView是专门写API的视图函数,结合serializers,非常方便做序列化!

关于APIView的源码解析,请参考文章:

https://blog.csdn.net/u013210620/article/details/79857654

 

GET

在request对象中
request.query_params 中可以获取?param1=32&param2=23形式的参数.
request.query_params 返回的数据类型为QueryDict
QueryDict转为普通python字典. query_params.dict()即可.

POST

post 请求参数都在请求体中, 但是其实你的url可以写成get的形式, 最终结果, 参数会有两部分组成, 一部分在url中, 一部分在http body 中, 但是非常不建议这样做.

接下来的代码编写也不会考虑这样的情况, post 仅考虑所有参数都在http body 中的情况.

 

提交类型参数位置参数类型
form-data提交, 参数在data中, 类型为QueryDict
application/json提交 参数在data中 类型为dict
(swagger)使用接口文档提交, 由于使用curl提交, 虽然是post 但是参数依然被类似get的形式拼接到了url之后, 此时 参数在query_params 中 类型为 QueryDict
x-www-form-urlencoded 参数在data中 类型为 QueryDict

 

PUT

提交类型参数位置参数类型
form-data request.data QueryDict
application/json request.data dict
x-www-form-urlencoded request.data QueryDict
(swagger) request.data dict

PATCH

 

提交类型参数位置参数类型
form-data request.data QueryDict
application/json request.data dict
x-www-form-urlencoded request.data QueryDict
(swagger) request.data dict

DELETE

提交类型参数位置参数类型
form-data request.data QueryDict
application/json request.data dict
x-www-form-urlencoded request.data QueryDict
(swagger) request.query_params QueryDict
iOS端提交和get情况一样 request.query_params QueryDict

更多详细信息,请参考:

https://www.jianshu.com/p/f2f73c426623

GenericAPIView

GenericAPIView对APIView再次封装,实现了强大功能:

  • 加入queryset属性,可以直接设置这个属性,不必再将实例化的courses,再次传给seriliazer,系统会自动检测到。除此之外,可以重载get_queryset(),这样就不必设置’queryset=*’,这样就变得更加灵活,可以进行完全的自定义。
  • 加入serializer_class属性与实现get_serializer_class()方法。两者的存在一个即可,通过这个,在返回时,不必去指定某个serilizer
  • 设置过滤器模板:filter_backends
  • 设置分页模板:pagination_class
  • 加入 lookup_field=”pk”,以及实现了get_object方法: 这个用得场景不多,但十分重要。它们两者的关系同1,要么设置属性,要么重载方法。它们的功能在于获取某一个实例时,指定传进来的后缀是什么。 

 

GenericAPIView的五个扩展类给我们提供了五个方法分别进行增删改查的不同操作,这样我们就不用写那么多函数啦!!

五个扩展类(为啥是5个?答:增删改查,查有两个)

搭配GenericAPIView使用

1.ListModelMixin: 提供list方法快速实现列表视图(多条数据)

2.CreateModelMixin: 提供create方法快速实现创建资源的视图

3.RetrieveModelMixin 提供retrieve方法,可以快速实现返回一个存在的数据对象(需要传入pk)

4.UpdateModelMixin 提供update方法,可以快速实现更新一个存在的数据对象。 提供partial_update方法,可以实现局部更新

5.DestroyModelMixin 提供destroy方法,可以快速实现删除一个存在的数据对象

 

注意:GenericAPIView不能单独使用,它需要和上面的5个扩展类配合使用才行

源码分析,请参考文章:

https://blog.csdn.net/u013210620/article/details/79869661

ListModelMixin

它返回数据列表,也就是多条数据

from rest_framework.mixins import ListModelMixin

RetrieveModelMixin 

它负责单条数据的获取、更新、删除

from rest_framework.mixins import RetrieveModelMixin

CreateModelMixin

它负责增加一条记录

from rest_framework.mixins import CreateModelMixin

DestroyModelMixin

 删除单条数据

from rest_framework.mixins import DestroyModelMixin

UpdateModelMixin

更新单条数据

使用时,需要导入模块

from rest_framework.mixins import UpdateModelMixin

RetrieveUpdateDestroyAPIView

用于读写删除端点来表示单个模型实例

提供getputpatchdelete方法处理。

from rest_framework.generics import RetrieveUpdateDestroyAPIView

举例:将CommentDetail改造成RetrieveUpdateDestroyAPIView

它拥有get,put,patch和delete方法处理,所以之前的那些方法,都可以干掉了!

from app01 import app01_serializers  # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin

# Create your views here.

class SchoolView(GenericAPIView, ListModelMixin):
    queryset = models.School.objects.all()
    serializer_class = app01_serializers.SchoolSerializer

    def get(self, request, *args, **kwargs):  # GET请求
        return self.list(request, *args, **kwargs)


# RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
    queryset = models.School.objects.all()
    serializer_class = app01_serializers.SchoolSerializer

    def get(self, request, pk, *args, **kwargs):  # GET请求
        return self.retrieve(request, pk, *args, **kwargs)


class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer

    def get(self, request, *args, **kwargs):  # GET请求
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):  # POST请求
        return self.create(request, *args, **kwargs)


class CommentDetail(RetrieveUpdateDestroyAPIView):
    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer
View Code

ListCreateAPIView

用于读写端点来表示模型实例的集合

提供getpost方法处理程序。

from rest_framework.generics import ListCreateAPIView

举例:将CommentView改造成ListCreateAPIView

它拥有get,post方法处理,所以之前的那些方法,都可以干掉了!

rom django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers  # 导入自定义的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin

# Create your views here.

class SchoolView(GenericAPIView, ListModelMixin):
    queryset = models.School.objects.all()
    serializer_class = app01_serializers.SchoolSerializer

    def get(self, request, *args, **kwargs):  # GET请求
        return self.list(request, *args, **kwargs)


# RetrieveModelMixin 表示查询单条数据,需要传入pk参数
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
    queryset = models.School.objects.all()
    serializer_class = app01_serializers.SchoolSerializer

    def get(self, request, pk, *args, **kwargs):  # GET请求
        return self.retrieve(request, pk, *args, **kwargs)


class CommentView(ListCreateAPIView):
    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer


class CommentDetail(RetrieveUpdateDestroyAPIView):
    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer
View Code

ModelViewSet

ModelViewSet视图集会自动提供list,create, retrieve, update & destroy这些行为,

查看源代码:它有6个功能

使用时,需要导入模块

from rest_framework.viewsets import ModelViewSet

处理器方法只有在定义了URLConf的时候才会绑定这些行为。 
在urls.py文件中,我们把ViewSet绑定到一些具体的视图上

修改app01_urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [

    # 评论
    url(r'comment/$', views.CommentViewSet.as_view({
        'get': "list",
        'post': 'create'
    })),

    url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    })),
]

一个视图函数,就搞定了5种请求方式,惊叹不已!

APIView和ModelViewSet,该如何取舍。看需求。如果用ModelViewSet,只能按照它要求的格式来走
如果想加入一点个性化的数据,比如{"code":0,"msg":None}还是得需要使用APIView

posted @ 2019-04-16 18:09  二号  阅读(220)  评论(0编辑  收藏  举报