源码分析

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. 病毒木马查杀实战第025篇:JS下载者脚本木马的分析与防御

    前言 这次我与大家分享的是我所总结的关于JS下载者脚本木马的分析与防御技术.之所以要选择这样的一个题目,是因为在日常的病毒分析工作中,每天都会遇到这类病毒样本,少则几个,多则几十个(当然了,更多的样本 ...

  2. Linux内核升级、GRUB2引导故障处理与密码破解

    目录 内核升级 GRUB2内核启动设置 GRUB2引导菜单加密 GRUB2引导故障及修复 救援模式管理 Rhel7破解root密码 内核升级 查看当前内核版本: uname  -r 查看可升级内核:  ...

  3. android CVE

    本文收集网上android cve的一些分析供后续学习: Android uncovers master-key:android1.6-4.0 由于ZIP格式允许存在两个或以上完全相同的路径,而安卓系 ...

  4. PHP Excel文件导入数据到数据库

    1.php部分(本例thinkphp5.1): 下载PHPExcel了扩展http://phpexcel.codeplex.com/ <?phpnamespace app\admin\contr ...

  5. PhpStorm个性化设置推荐

    预览 字体 字体使用jetbrains的mono,前往下载:如何安装,字体安装完成之后Restart,可在PhpStorm settings中搜索 font 进行启用 mono 字体 主题 主题推荐使 ...

  6. Windows bat批处理删除指定N天前的文件

    1:新建批处理文件:del_old_file.bat,更改系统时间为7天前,在c盘sql back 目录下新建测试文件,再将系统时间改为正确时间 2:编辑内容: rem 删除C:\sql back目录 ...

  7. 查询某软件所连接的外网IP地址

    一:背景环境: 1>:某机械公司用的某些特殊软件,需要实现所有使用某软件的屏蔽其软件所连接的外网ip,其他上网功能不做限制. 二:需求分析:可以查出此软件所连接的外网ip,在路由器的ip过滤中将 ...

  8. restful 与 webapi 详解

    restful 什么是API API全称Aplication Programming Itererface即应用程序编程接口, 我们在开发应用程序时经常用到.API作为接口,用来"连接&qu ...

  9. 『动善时』JMeter基础 — 20、JMeter配置元件【HTTP Cookie管理器】详细介绍

    目录 1.HTTP Cookie管理器介绍 2.HTTP Cookie管理器界面详解 3.JMeter中对Cookie的管理 (1)Cookie的存储 (2)Cookie的管理策略 4.补充:Cook ...

  10. zimbra启用SMTP认证

    zmprov modifyServer {{ you domain }} zimbraMtaTlsAuthOnly FALSE zmcontrol restart 查看对应配置 zmprov getS ...