源码分析

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. Android内核的编译和调试

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/70500488 一.Android内核源码的选择 Android手机设备内核源码的调 ...

  2. hdu1316 大数

    题意:      给你一个区间,问这个区间有多少个斐波那契数. 思路:      水的大数,可以直接模拟,要是懒可以用JAVA,我模拟的,打表打到1000个就足够用了... #include<s ...

  3. The 2014 ACM-ICPC Asia Mudanjiang Regional First Round J

    题意:       是个模拟题,就是给你一个字符串,问你他是不是"ABABA" 或者"ABABCAB"的模式,ABC是三个长度不为0且不同的串. 思路:     ...

  4. 测开之Python自动化全栈工程师+性能专项(送思维导图)

    测开之Python自动化全栈工程师+性能专项 功能测试基础 接口测试基础接口的通信原理与本质cookie.session.token详解接口测试的意义与测试方法接口测试用例的设计 app测试 app流 ...

  5. Catalan数以及相关性质的证明

    \(Catalan\) 数相关证明 Mushroom 2021-5-14 \(Catalan\)数的定义 给定一个凸\(n + 1\)边形, 通过在内部不相交的对角线,把它划分成为三角形的组合,不同的 ...

  6. Codeforces Round #688 (Div. 2)

    A. Cancel the Trains 题意:给定两个数组,找出这两个数组中有多少重复元素,然后输出 思路:直接找 代码: 1 #include<iostream> 2 #include ...

  7. 从系统的角度分析影响程序执行性能的因素——SA20225205 黄兴宇

    实验总结分析报告:从系统的角度分析影响程序执行性能的因素 1.请您根据本课程所学内容总结梳理出一个精简的Linux系统概念模型,最大程度统摄整顿本课程及相关的知识信息,模型应该是逻辑上可以运转的.自洽 ...

  8. 在Visual Studio 中使用git——文件管理-中(五)

    在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...

  9. 【Mysql】数据库事务,脏读、幻读、不可重复读

    一.什么是数据库事务 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位.事务由事务开始与事务结束之间 ...

  10. JAVA基础——标识符和数据类型

    注释 单行注释 // 多行注释 /* */ 文档注释 /***/ 标识符和关键字 所有的标识符都应该以字母(A-Z或者a-z),美元符号($),或者下划线(_)开始 首字符之后可以时字母(A-Z或者a ...