Django(55)GenericAPIView源码分析
源码分析
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源码分析的更多相关文章
- Django搭建及源码分析(三)---+uWSGI+nginx
每个框架或者应用都是为了解决某些问题才出现旦生的,没有一个事物是可以解决所有问题的.如果觉得某个框架或者应用使用很不方便,那么很有可能就是你没有将其使用到正确的地方,没有按开发者的设计初衷来使用它,当 ...
- Django如何启动源码分析
Django如何启动源码分析 启动 我们启动Django是通过python manage.py runsever的命令 解决 这句话就是执行manage.py文件,并在命令行发送一个runsever字 ...
- Django之DRF源码分析(二)---数据校验部分
Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...
- django 之(二) --- 源码分析
CBV类视图继承 CBV:继承自View:注册的时候使用的as_view() 入口 不能使用请求方法的名字作为参数的名字 只能接受已经存在的属性对应的参数 定义了一个view 创建了一个类视图对象 保 ...
- Django rest framework源码分析(3)----节流
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- Django rest framework源码分析(1)----认证
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- Django rest framework 源码分析 (1)----认证
一.基础 django 2.0官方文档 https://docs.djangoproject.com/en/2.0/ 安装 pip3 install djangorestframework 假如我们想 ...
- django CBV视图源码分析
典型FBV视图例子 url路由系统 from django.conf.urls import url from django.contrib import admin from luffycity.v ...
- Django rest framework源码分析(一) 认证
一.基础 最近正好有机会去写一些可视化的东西,就想着前后端分离,想使用django rest framework写一些,顺便复习一下django rest framework的知识,只是顺便哦,好吧. ...
随机推荐
- 如何在C或C++代码中嵌入ARM汇编代码
转载自:http://blog.csdn.net/roland_sun/article/details/42921131 大家知道,用C或者C++等高级语言编写的程序,会被编译器编译成最终的机器指令. ...
- hdu5256序列变换(非递减子序列)
题意(中文直接粘吧)序列变换 Problem Description 我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增.其中无论是修改前还是修改后,每个元 ...
- 一个不错的过TP思路,转载CSDN
也许大家也是研究腾讯游戏的爱好者,对腾讯的游戏都有过这样的体会 例如OD与CE无法进行如以下操作: 无法附加进程, 无法打开进程, 游戏进程被隐藏无法在工具中查看到,内存无法读取代码 内存修改后游 ...
- 容器随Docker启动而启动
在容器开启状态下 docker container update --restart=always 容器名
- java之I/O流
I/O流的使用情况多种多样,首先它的数据源就可能是文件.控制台.服务器等,它的单位可能是按字节.按字符.按行等.为了涵盖所有的可能,java类库中创建了大量的类,如此多的类让我们在使用时感觉有点难以选 ...
- 【Linux】在centos中使用命令安装redis
1.前提centos能够上网 测试方式输入命令,有数据返回即可.如果则先配置centos网络连接. ping www.baidu.com 2.安装gcc 输入命令进行安装 yum install gc ...
- ACM、考研、就业,在我心底已经有了明确的答案_人生没有完整的,只有无悔的
思绪再三,还是决定放弃了ACM,走上考研路(我现在是大二下学期,马上结束).虽然我们ACM的带队老师经常说:"ACM和考研是不冲突的",但是我感觉做ACM和考研的关系不是很紧密,而 ...
- Django(7)url命名的作用
前言 为什么我们url需要命名呢?url命名的作用是什么?我们先来看一个案例 案例 我们先在一个Django项目中,创建2个App,前台front和后台cms,然后在各自app下创建urls.py文件 ...
- Asp.NetCore Web开发之会话技术
这节讲一下会话技术,首先了解一下什么是会话,会话是指浏览器打开到关闭的过程中,多次与服务器发送接收数据的过程. 由于HTTP是无状态协议,一次请求响应过后,产生的数据就随之释放了,可是在某些情况下,我 ...
- Linux_控制服务与守护进程
一.systemd 1.systemd简介 1️⃣:systemd是用户空间的第一个应用程序,即/sbin/init 2️⃣:init程序的类型: SysV风格:init(centos5),实现系统初 ...