【七】序列化保存save源码
【1】介绍
- 无论是创建还是修改数据,都需要执行save方法,再前面的使用中都没有再里面添加过参数
- 其实save中可以给额外参数
- 比如
.save(time=datetime.datetime.now())
- 这个需要模型表中有time的字段,结果就是将当前时间也保存在表中,不用经过数据校验
【2】需要的基础知识
(1)assert
assert
是 Python 中用于调试的一个关键字,它允许程序员在代码中设置检查点,以确保程序在运行时满足特定的条件。- 如果条件为真(
True
),则assert
语句不会做任何事情,程序将继续执行。 - 如果条件为假(
False
),assert
会引发一个AssertionError
异常,通常还伴随着一个可选的错误消息,用于解释断言失败的原因。
- 如果条件为真(
(2)反射方法hastattr
-
hasattr
是 Python 的内置函数,用于检查对象是否具有特定的属性。- 这个函数接受两个参数:一个对象和一个字符串,该字符串表示要检查的属性名。
- 如果对象具有该属性,
hasattr
返回True
;否则,返回False
。
-
详情请见:Python 面向对象之反射_python对象反射-CSDN博客
(3)示例
class A:
class_name = "A"
try:
a = A()
assert hasattr(a, 'class_name'), ('Don`t have class_name')
assert hasattr(a, 'name'), ('Don`t have name')
except Exception as e:
print(e)
# Don`t have name
- 最外层用
try
来捕获异常,如果发现了异常那么就执行异常的输出print(e)
- 首先实例化一个对象a
- 然后使用两个断言,每个断言的前面是一个反射方法,对实例a进行属性的判断,
- 在返回True,那么就不会执行断言后面的参数;
- 不在返回False,那么会返回后面的报错描述信息
【3】分析源码
- 这是序列化类的save方法源码
def save(self, **kwargs):
assert hasattr(self, '_errors'), (...)
assert not self.errors, (...)
assert 'commit' not in kwargs, (...)
assert not hasattr(self, '_data'), (...)
validated_data = {**self.validated_data, **kwargs}
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
assert self.instance is not None, ()
else:
self.instance = self.create(validated_data)
assert self.instance is not None, ()
return self.instance
-
首先执行了四个断言
hasattr(self, '_errors')
:检查对象是否有_errors
属性。这个属性是在.is_valid()
后设置的,如果没有说明没进行反序列化检查assert not self.errors
:检查对象errors
属性是否为空。有值说明数据检验不通过'commit' not in kwargs
:防止用户错误地传递'commit'
参数给save()
方法,并提示用户正确的使用方式。not hasattr(self, '_data')
:这个断言确保在访问serializer.data
属性之后没有调用.save()
方法。访问serializer.data
通常意味着序列化器的数据已经被渲染成输出格式(如 JSON),此时再调用.save()
可能会导致不一致或错误的状态
-
重点来了
validated_data = {**self.validated_data, **kwargs}
- 首先
validated_data
这个是通过校验的所有数据,是普通的字典格式(querydict
就不是普通字典格式),普通字典格式可以使用**
进行打散,即{"name":"bruce"}
将变成name=bruce
,打散放在字典中 kwargs
是就是我们自定义传进来的信息,同样的进行打散,放在通过校验的数据中,所以我们可以直接在save方法中进行传值
- 首先
-
接下来就是进行实例
instance
的判断- 没有实例
instance
,说明是创建实例,即调用create
方法 - 有实例
instance
,说明就是要修改操作,即调用update
方法
- 没有实例
-
创建或修改完成后,同样通过断言
assert self.instance is not None, ()
确保self.instance
不是None
。- 这也是一个安全检查,确保创建操作成功返回了一个实例。