django restframework(DRF)
最近的开发过程当中,发现restframework的功能很强大,所以尝试解读了一下源码,写篇博客分享给大家,有错误的地方还请各位多多指出
视图部分
视图部分,主要负责查询方法,在编写代码的过程当中,按照具体功能和请求动作进行了拆分,方便开发者进行自定义的拼接。
mixin
Mixin 即 Mix-in,常被译为“混入”,是一种编程模式,
像C或C++这类语言都支持多重继承,一个子类可以有多个父类,这样的设计常被人诟病。因为继承应该是个”is-a”关系。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?(这段是网络上一个老大哥的话,我这里引用一下,感觉特别有道理)
功能部分
功能部分来源于restframework定义的mixin文件当中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EsyPJDfK-1608107829157)(file:///C:/Users/dell/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]
翻译:基于类的通用视图的基本构建块。 我们还没有将行为绑定到http方法处理程序, 它允许mixin类以有趣的方式组合。
在这里提供了下面的几个方法,这些方法无论在自定义接口或者DRF操作的时候都在平凡的继承使用,为开发者提供了更加灵活的开发类拼接方式。但是要注意的是这里并没有强调具体的请求方式,比如GET请求进行数据展示,所以给开发者更细粒度的类拼接开发可能,下面是mixin包含的所有方法:
具体功能
我们首先列出这些方法的功能:
CreateModelMixin: 创建一个模型实例。
ListModelMixin: 列出一个数据,返回的格式是django熟悉的queryset格式,注意,在这里并没有返回字典或者JSON,这部分工作并不归他管理。
RetrieveModelMixin:检索一个数据。
UpdateModelMixin:跟新一个模型数据。
DestroyModelMixin: 摧毁一个数据模型,注意这里是摧毁而不是删除,所以想要逻辑删除的小伙伴要注意了
源码分析
我们以CreateModelMixin的源码为例子,来看一下mixin的功能
class CreateModelMixin:
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
1、serializer = self.get_serializer(data=request.data)
在这段代码当中,可能好多小伙伴会很疑惑,当前这个文件很简单,但是有很多方法实际上现在是找不到的,比如get_serializer这个方法,实际上,在这个文件当中确实没有,这个方法来源与DRF的另外的一个模块,数据序列化的方法,rest_framework.generics.GenericAPIView:
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
返回一个用于序列化和反序列化输入的可以进行数据校验的序列化实例。
"""
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs)
接着看
2、serializer.is_valid(raise_exception=True) #raise_exception 是否引发异常,默认为False,源码如下:
def is_valid(self, raise_exception=False):
assert hasattr(self, 'initial_data'), (
'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
if not hasattr(self, '_validated_data'):
try:
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
if self._errors and raise_exception:
raise ValidationError(self.errors)
return not bool(self._errors)
然后,这句就很好理解了,就是进行数据校验的过程。
3、self.perform_create(serializer)
这句就是当前类编写的一个保存方法
4、
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
这里就是对保存后的数据头部和响应的包装,有兴趣的同学可以看一声Response的源码:
"""
The Response class in REST framework is similar to HTTPResponse, except that
it is initialized with unrendered data, instead of a pre-rendered string.
REST框架中的响应类类似于HTTPResponse,除了它是用未呈现的数据而不是预先呈现的字符串初始化的。
The appropriate renderer is called during Django's template response rendering.
在Django的模板响应呈现期间调用适当的呈现器,比如json
"""
from http.client import responses
from django.templ