源码分析

GenericAPIView继承自APIView,也就是在APIView基础上再做了一层封装,源码如下:

class GenericAPIView(views.APIView):
queryset = None
serializer_class = None lookup_field = 'pk'
lookup_url_kwarg = None filter_backends = api_settings.DEFAULT_FILTER_BACKENDS pagination_class = api_settings.DEFAULT_PAGINATION_CLASS def get_queryset(self):
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
) queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all()
return queryset def get_object(self):
queryset = self.filter_queryset(self.get_queryset()) lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field assert lookup_url_kwarg in self.kwargs, (
'Expected view %s to be called with a URL keyword argument '
'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
) filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs) self.check_object_permissions(self.request, obj) return obj def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs) def get_serializer_class(self):
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
) return self.serializer_class def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
} def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset @property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator def paginate_queryset(self, queryset):
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self) def get_paginated_response(self, data):
assert self.paginator is not None
return self.paginator.get_paginated_response(data)

我们可以看到GenericAPIView中定义了6个类属性和8个方法,接下来一个个分析

类属性

  • queryset = None
  • serializer_class = None
  • lookup_field = 'pk'
  • lookup_url_kwarg = None
  • filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
  • pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

queryset

  queryset是用来控制视图返回给前端的数据。如果没什么逻辑,可以直接写在视图的类属性中,如果逻辑比较复杂,也可以重写get_queryset方法用来返回一个queryset对象。如果重写了get_queryset,那么以后获取queryset的时候就需要通过调用get_queryset方法。因为queryset` 这个属性只会调用一次,以后所有的请求都是使用他的缓存。

serializer_class

  serializer_class用来验证和序列化数据的。也是可以通过直接设置这个属性,也可以通过重写get_serializer_class来实现。

lookup_field

在检索的时候,根据什么参数进行检索。默认是pk,也就是主键。

lookup_url_kwarg

在检索的url中的参数名称。默认没有设置,跟lookup_field保持一致。

filter_backends

用于查询集过滤的过​​滤器类,默认是[]

pagination_class

用于查询集分页的样式。默认为None

方法

  • get_queryset
  • get_object
  • get_serializer
  • get_serializer_class
  • get_serializer_context
  • filter_queryset

get_queryset

def get_queryset(self):
# 断言queryset是否不为None
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
) # 定义queryset属性,获取父类的queryset,如果父类没有定义类属性`queryset`,那么默认值就是None,就会报上面断言的错误
queryset = self.queryset
# 如果queryset是QuerySet对象,那么返回全部内容
if isinstance(queryset, QuerySet):
queryset = queryset.all()
# 如果不是queryset,那么直接返回
return queryset

get_queryset默认是返回数据库全部数据,如果想返回其他数据,需要自定义

get_object

def get_object(self):
queryset = self.filter_queryset(self.get_queryset()) # 查找过滤的条件,默认是pk
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field assert lookup_url_kwarg in self.kwargs, (
'Expected view %s to be called with a URL keyword argument '
'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
) filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs) # 可能会引发权限被拒绝
self.check_object_permissions(self.request, obj) return obj

该方法是用于在数据检索(通过pk查找)的时候,返回一条数据的。

get_serializer

def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs)

返回应该用于验证和反序列化输入以及序列化输出的序列化器实例

get_serializer_class

def get_serializer_class(self):
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
) return self.serializer_class

返回用于序列化的类。默认使用self.serializer_class。如果您需要根据传入请求提供不同的序列化,您可能需要重写它。

get_serializer_context

def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}

提供给序列化的额外上下文。

filter_queryset

def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset

给定一个查询集,使用正在使用的过滤器对其进行过滤。您不太可能想要覆盖此方法,但如果您想将配置的过滤后端应用到默认查询集,您可能需要从列表视图或自定义get_object 方法中调用它。

实战案例

class StudentsGenericView(GenericAPIView):
queryset = Student.objects.all() # 定义了类属性queryset,告诉视图要针对哪个模型做处理
serializer_class = StudentModelSerializer # 定义类属性serlializer_class,告诉视图你的序列化的类是什么
def get(self, request, *args, **kwargs):
pk = kwargs.get("pk")
if pk:
many = False
query = self.get_object() # 通过pk检索数据,返回一条数据
else:
many = True
query = self.get_queryset() # 返回动态的数据集,默认返回全部
serializer = self.get_serializer(query, many=many) # 如果数据对象是queryset对象,many需要为True
return APIResponse(results=serializer.data)

Django(55)GenericAPIView源码分析的更多相关文章

  1. Django搭建及源码分析(三)---+uWSGI+nginx

    每个框架或者应用都是为了解决某些问题才出现旦生的,没有一个事物是可以解决所有问题的.如果觉得某个框架或者应用使用很不方便,那么很有可能就是你没有将其使用到正确的地方,没有按开发者的设计初衷来使用它,当 ...

  2. Django如何启动源码分析

    Django如何启动源码分析 启动 我们启动Django是通过python manage.py runsever的命令 解决 这句话就是执行manage.py文件,并在命令行发送一个runsever字 ...

  3. Django之DRF源码分析(二)---数据校验部分

    Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...

  4. django 之(二) --- 源码分析

    CBV类视图继承 CBV:继承自View:注册的时候使用的as_view() 入口 不能使用请求方法的名字作为参数的名字 只能接受已经存在的属性对应的参数 定义了一个view 创建了一个类视图对象 保 ...

  5. Django rest framework源码分析(3)----节流

    目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...

  6. Django rest framework源码分析(1)----认证

    目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...

  7. Django rest framework 源码分析 (1)----认证

    一.基础 django 2.0官方文档 https://docs.djangoproject.com/en/2.0/ 安装 pip3 install djangorestframework 假如我们想 ...

  8. django CBV视图源码分析

    典型FBV视图例子 url路由系统 from django.conf.urls import url from django.contrib import admin from luffycity.v ...

  9. Django rest framework源码分析(一) 认证

    一.基础 最近正好有机会去写一些可视化的东西,就想着前后端分离,想使用django rest framework写一些,顺便复习一下django rest framework的知识,只是顺便哦,好吧. ...

随机推荐

  1. LA3635派

    题意:       有F+1个人来分n个圆形派,每个人分到的必须是一个整块的派,形状无所谓,每个人分到的必须一样多,给你每个派的半径,问每个人能分到的最大派的面积是多少. 思路:       虽然不是 ...

  2. LA3029最大子矩阵

    题意:       给你一个n*m的矩阵<每个格子不是'F'就是'R'>,让你找一个最大的'F'矩阵,输出他的面积*3. 思路:       比较经典的题目了,现在想起来比较好想,以前的话 ...

  3. hdu5012 水搜索

    题意:       给你一个正方体的初始状态和末状态,问你是否可以再6步之内转到这个状态,有四种转的方式,如果你面对的是正方向的正前方,那么转的方式就是 顺时针,逆时针,上,下. 思路:        ...

  4. 【python】Leetcode每日一题-删除有序数组中的重复项2

    [python]Leetcode每日一题-删除有序数组中的重复项2 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不 ...

  5. 【python】Leetcode每日一题-二叉搜索迭代器

    [python]Leetcode每日一题-二叉搜索迭代器 [题目描述] 实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器: BSTIterator(T ...

  6. 多线程-3.sleep() yield() join()

    1.sleep()方法 jdk文档描述:Causes the currently executing thread to sleep (temporarily cease execution) for ...

  7. Js的变量、作用域与内存

    变量.作用域与内存 1 .原始值与引用值 Undefined.Null.Boolean.Number. String和Symbol.保存原始值的变量是按值(by value)访问的 引用值是保存在内存 ...

  8. 使用MindSpore的线性神经网络拟合非线性函数

    技术背景 在前面的几篇博客中,我们分别介绍了MindSpore的CPU版本在Docker下的安装与配置方案.MindSpore的线性函数拟合以及MindSpore后来新推出的GPU版本的Docker编 ...

  9. 一文弄懂pytorch搭建网络流程+多分类评价指标

    讲在前面,本来想通过一个简单的多层感知机实验一下不同的优化方法的,结果写着写着就先研究起评价指标来了,之前也写过一篇:https://www.cnblogs.com/xiximayou/p/13700 ...

  10. font 和 text ,cursor

    font:14px/30px/"宋体"这种写法等于 font-size="14px" line-heigiht="30px" font-fa ...