Django源码解析之视图

2019-04-01  本文已影响0人  小码码

1 认证源码分析

资料链接:http://www.sohu.com/a/222215490_729271

2 处理请求wsgi分析与视图View

资料链接:https://blog.csdn.net/qq_33339479/article/details/78879571

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
 # Ensure that the incoming request is permitted
        self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)
from django.http import QueryDict

继承APIView的类:
get 获取参数:params = req.query_params
post/put/delete获取参数:params = req.data

APIView支持定义的属性:

3.2 GenericAPIView(继承自APIView)

GenericAPIView较APIView有了更多的封装:增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

# 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 ,只有两者值不相同时才需要分别单独设置。
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个类扩展方法主要是对数据的增删改查进行封装.

def perform_create(self, serializer):
# 重写save的逻辑,除了serializer.save()外,还需要对course的收藏数fav_num加1
    instance = serializer.save()
    course = instance.course
    course.fav_num += 1
    course.save()
3.4 子类视图

rest_framework.generics里面除了提供GenericAPIView以外,还有CreateAPIView/ListAPIView/RetrieveAPIView/DestroyAPIView/UpdateAPIView/ListCreateAPIView/RetrieveUpdateAPIView/RetrieveDestroyAPIView/RetrieveUpdateDestroyAPIView 9个子类视图,这些视图函数无非都是GenericAPIView与上面mixins的5个类扩展的各种组合.例如:

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类的关系图:

3.6.1 viewSet类视图与url的绑定方法
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'})),
]
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'),
]
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).

上一篇 下一篇

猜你喜欢

热点阅读