一文DRF序列化与反序列化
在做django前后端分离项目的时候,对django序列化与反序列化这一点,理解得不是很透彻,网上这方面资料又很少,所以今天又重新进行了设计演算以及DEBUG,有点收获,做下总结,分享一下。
DRF的序列化 - Serializer
首先,为什么要序列化
在前后端分离的web项目中,设计都是基于RESTful 架构的(不了解的可以看阮一峰大神的”理解RESTful“和”RESTful API设计指南“),前后端交互的数据类型一般为两种,json和xml,相对而言,json是主流数据类型。
在python web开发中,我们需要面临的问题是,我们在后端项目中,交互的数据一般为原生的python数据类型,比如dict、list、str等,那么要去和前端交互数据,必须要将原生python数据转换为json格式数据.
那为什么我们要用DRF的序列化
如果按照我们django的CBV开发,我们可能会这样做:
class GoodsView(View):
def get(self,request):
goods_list = list()
goods = Goods.objects.all()[0]
for good in goods:
goods_dict = dict()
goods_dict["font_image"] = good.goods_front_image
goods_dict["add_time"]=good.add_time
goods_list.append(goods_dict)
return JsonResponse(goods_list,safe=False)
我们将从数据库中查询出实例,然后将部分或者所有的字段,保存到dict中,然后存放到列表里面,通过jsonResponse转换成json数据,返回给请求用户。这里面有一个坑,那就是序列化的字段如果是一个image字段,那么就会显示无法序列化。其实也是可以解决,我们调用django自带的serializer方法,也能做到image字段序列化:
class GoodsView(View):
def get(self,request):
goods_list = list()
goods = Goods.objects.all()[:10]
# for good in goods:
# goods_dict = dict()
# goods_dict["font_image"] = good.goods_front_image
# goods_dict["add_time"]=good.add_time
# goods_list.append(goods_dict)
goods_json_data = serializers.serialize("json",goods)
goods_json_data = json.loads(goods_json_data)
return JsonResponse(goods_json_data,safe=False)
但它其实有很多的缺陷,比方说,不能只能的给我上传文件加上media路径,以及域名,这可能需要前端手动添加,耗费更多的工作时间。
DRF的序列化功能解决了这些顾虑:
class GoodsSerializer(serializers.Serializer):
name = serializers.CharField(max_length=300)
click_num = serializers.IntegerField(default=0)
可以看出,代码量更少,而且实现了更加强大的功能。
序列化做了什么
经过上面的总结,我们其实不难得出,序列化做了:
instance -> native_data -> json
的转换,当然官方文档也是这么做解释的
反序列化 - Serialization
什么是反序列化
上文已经解释过序列化了,那么根据字面意思,我们也能得出,反序列化其实是做:
json -> native_data -> instance -> sql_data
的转换,反序列化就是做了序列化相反的事情.
DRF 反序列化的实现
DRF 源码里,为我们提供了两种方法,create和update,重载这两个方法,我们可以通过这两个方法创建一个或者更新一个实例,在里面调用save方法对实例数据进行保存。
也就是说,DRF的反序列化实现了类似于Django form的保存机制。