1 认证源码分析
资料链接:http://www.sohu.com/a/222215490_729271
2 处理请求wsgi分析与视图View
资料链接:https://blog.csdn.net/qq_33339479/article/details/78879571
- 基类View的简要分析
在url中,调用View类中的as_view方法,此时就会调用as_view中的view方法,该方法最终调用View类的self.dispatch,通过筛选后调用相应的handler处理。 handler对应的就是get/post/put/delete等具体的方法。所以在继承View的class中,只要重新定义了get/post/put/delete方法,URL调用时会自动进入该类相应的方法中。
3 视图类的对比分析
资料链接:https://blog.csdn.net/odyssues_lee/article/details/80895207
3.1 APIView与View的不同(APIView继承与View)
from django.views import View
from rest_framework.views import APIView
- (1) View来自django.views,APIView来自rest_framework.views,APIView比View有更多的封装,且APIView继承于View。
- (2) APIView传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
- (3)视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
- (4) 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
- (5)在进行dispatch()分发前,多了对请求进行身份认证、权限检查、流量控制。对应的源码如下:
# Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
- (6)获取参数的区别
继承View的类:
get 获取参数:params = req.GET
post 获取参数:params = req.POST
put/delete获取参数:params = QueryDict(req.body)
from django.http import QueryDict
继承APIView的类:
get 获取参数:params = req.query_params
post/put/delete获取参数:params = req.data
APIView支持定义的属性:
- authentication_classes 列表或元祖,身份认证类
- permissoin_classes 列表或元祖,权限检查类
- throttle_classes 列表或元祖,流量控制类
3.2 GenericAPIView(继承自APIView)
GenericAPIView较APIView有了更多的封装:增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。
- 多了属性:
queryset 列表视图的查询集
serializer_class 视图使用的序列化器
pagination_class 分页控制类
filter_backends 过滤控制后端
lookup_field 查询单一数据库对象时使用的条件字段(lookup_field的值为数据库表里的字段),默认为'pk'
lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
# lookup_field与lookup_url_kwarg的使用举例
url(r"^config/(?P<id>/$", views.TestView.as_view()),
class TestView(mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
"""改配置"""
queryset = Config.objects.all()
lookup_field = ('uuid')
lookup_url_kwarg = ('id')
def put(self, request, *args, **kwargs):
instance = self.get_object()
# get_object会根据lookup_field 和lookup_url_kwarg 的值来过滤获取单个对象,过滤方法相当于:filter(uuid=id参数的值)。
# uuid为数据库表里的字段,id为参数中的关键字,即获取的是字段uuid=id参数的值的对象。通常lookup_url_kwarg 默认就是lookup_field 的值,代码中只需要设置lookup_field ,只有两者值不相同时才需要分别单独设置。
- 多提供的方法:
get_queryset(self):返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
get_serializer_class(self)返回序列化器类,默认返回serializer_class,可以重写,例如:
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
get_serializer(self, args, *kwargs)返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。
get_object(self):返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。
若详情访问的模型类对象不存在,会返回404。
get_serializer_context:获取序列化的数据,定义了某种格式的字典
class BookDetailView(GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request, pk):
book = self.get_object()
serializer = self.get_serializer(book)
return Response(serializer.data)
3.3 配合使用的5个类扩展(from rest_framework import mixins)
宏观感受: mixins的这5个类扩展方法主要是对数据的增删改查进行封装.
ListModelMixin:提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。
CreateModelMixin:提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。在一些情境下,我们需要对里面的perform_create( )进行重写。例如:
def perform_create(self, serializer):
# 重写save的逻辑,除了serializer.save()外,还需要对course的收藏数fav_num加1
instance = serializer.save()
course = instance.course
course.fav_num += 1
course.save()
RetrieveModelMixin:提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。对retrieve这个方法的重写几率比较高,例如我们在增加点击数的时候,经常要对其进行一个重写。
UpdateModelMixin:提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。如果需要对更新这个逻辑进行自定义,那么需要重写perform_update( )方法,而尽量少去重写update( )
DestroyModelMixin:提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
3.4 子类视图
rest_framework.generics里面除了提供GenericAPIView以外,还有CreateAPIView/ListAPIView/RetrieveAPIView/DestroyAPIView/UpdateAPIView/ListCreateAPIView/RetrieveUpdateAPIView/RetrieveDestroyAPIView/RetrieveUpdateDestroyAPIView 9个子类视图,这些视图函数无非都是GenericAPIView与上面mixins的5个类扩展的各种组合.例如:
- 1) CreateAPIView
提供 post 方法,继承自: GenericAPIView、CreateModelMixin - 2)ListAPIView
提供 get 方法,继承自:GenericAPIView、ListModelMixin - 3)RetireveAPIView
提供 get 方法,继承自: GenericAPIView、RetrieveModelMixin - 4)DestoryAPIView
提供 delete 方法,继承自:GenericAPIView、DestoryModelMixin - 5)UpdateAPIView
提供 put 和 patch 方法,继承自:GenericAPIView、UpdateModelMixin - 6)RetrieveUpdateAPIView
提供 get、put、patch方法,继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin - 7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法,继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
3.5 视图类的使用举例
参考资料1:https://blog.csdn.net/u013210620/article/details/79869661
BookView是对book表的所有记录查询、增加某些数据记录
BookViewDetail是对book表单条数据的查询、修改、删除
from rest_framework import mixins
from rest_framework import generics
#ListModelMixin适用于查询数据列表
class BookView(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
/*
RetrieveModelMixin 适用于查询单个对象的详情数据,
UpdateModelMixin 适用于更新单条数据
DestroyModelMixin 删除单条数据
*/
class BookViewDetail(
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
mixins.UpdateModelMixin,
generics.GenericAPIView
):
queryset = Book.objects.all()
serializer_class = BookSerializers
def get(self,request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def delete(self,request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
def put(self,request, *args, **kwargs):
return self.update(request, *args, **kwargs)
3.6 viewSet视图
django中除了上面提到的GenericAPIView等视图外,还有一类很重要的视图函数--ViewSet类视图,viewsets.py文件中提供的.
参考资料:https://blog.csdn.net/u013210620/article/details/79879611
https://www.jianshu.com/p/2c3fc8060a63
几种ViewSet类的关系图:
- 基类ViewSetMixin中重写了as_view()方法,方便了对API路由的管理.
3.6.1 viewSet类视图与url的绑定方法
- 方法一:action中绑定
ViewSetMixin的as_view()方法中提供了actions参数,可以利用action参数将get/post/put/delete等方法与list/create/update/destroy等动作关联起来.使用举例:
urlpatterns = [
url(r"bookset/$",BookSet.as_view({'get': 'list', 'post': 'create'})),
url(r"bookset/(?P<pk>\d+)/$",BookSet.as_view({'get': 'retrieve', 'put': 'update','delete': 'destroy'})),
]
- 方法二:action中绑定方式二
这种方法的本质同方法一,只不过是将as_view的绑定过程抽出来了,例如:
book_list = BookSet.as_view({
'get': 'list',
'post': 'create'
})
book_detail = BookSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
urlpatterns = [
url(r'^bookset/$', book_list, name='book-list'),
url(r'^bookset/(?P<pk>\d+)/$', book_detail, name='book-detail'),
]
- 方法三:routers自动绑定
使用举例:
from django.conf.urls import url,include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'bookset', BookSet)
urlpatterns = [
url(r'^', include(router.urls)),
]
备注:router的方式中虽然没有定义name参数,但router内部会自动生成,name的格式同方法二中name的格式.
3.7 @list_route和@detail_route的使用
list_route和detail_route装饰器是为了能在Viewset中自定义方法而提供的.两者的区别是list_route对应的detail=False,detail_route对应的detail=True,也就是list_route对应的是一般列表,而detail_route需要返回详情.
在DRF 3.10这个版本后使用 @action 代替了 @list_router和@detail_router。
@detail_route 相当于 @action(detail=True).
@list_route 相当于 @action(detail=False).