这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题
于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。
微信小程序搜索:Python面试宝典
或可关注原创个人博客:https://lienze.tech
也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习
Response是不能直接返回ORM数据的,所以需要我们进行序列化操作,可以通过手动将其转为字典或JSON***,也可以使用DRF所提供的序列化器,我们一般建议您使用序列化器*,这个更专业,更简单,并且格式更为统一
如果你经常使用的是自己去将数据封装为***JSON***,那么常见的代码模型就像这样
data = models.objects.all()
json_ = {}
for d in data:
json_['age'] = d.age
json_['name'] = d.name
return Response(json_)
字段多了的话,这个工作量就会越来越麻烦了,而且有关于时间(DateTimeField、DateField)等字段类型的序列化直接通过***JSON***也是不行的,需要自己手动编写**JSON的序列化器,非常麻烦,于是乎 DRF 就提供了更为便捷的两种序列化器,普通序列化器与模型序列化器
from rest_framework import serializers
普通序列化器,可以按照给定字段,将所匹配的ORM数据字段转换为***JSON***数据,不光可以对一条数据,也可以对一个**QuerySet所对应的结果集
比如一个课程表有如下一些字段
class Course(models.Model):
name = models.CharField(max_length=20, verbose_name='课程名字')
created = models.DateField(verbose_name='课程创建时间')
def __str__(self):
return self.name
测试数据可以通过数据库手动添加
那么普通序列化器就可以定义如下,按照模型类字段支持即可,非常简单
class CourseSer(serializers.Serializer):
name = serializers.CharField(max_length=20)
created = serializers.DateField(auto_now_add=True)
普通的序列化器,不光可以为数据库模型类定义,也可以为非数据库模型类的数据定义,只是这里为模型类定义时,需要根据模型类字段一一映射
序列化就是将ORM数据放入序列化器加工,诞生出***JSON***数据对象,序列化器对象的 data 属性即为处理好的 JSON 数据对象
单挑数据的序列化很简单,直接通过序列化器类对象的参数***instance***传入查询得到的结果即可
object = models.objects.get(pk=1)
ser_data = Serializer(instance=object)
ser.data # 这就是这一条数据的 JSON 结果
如果使用像***filter***、all这样的一些ORM方法,获取到的是QuerySet结果集,不是单独数据对象,那么使用序列化器时,需要传入many=True参数,用来表示:哇哦~,好多数据呢
objects = models.objects.all()
ser_data = Serializer(instance=objects, many=True)
ser_data.data # 这就是这一群数据的 JSON 结果
反序列化的概念很简单,就是把JSON等数据变为ORM数据对象,甚至是入库或者是修改**
DRF要求序列化器必须对数据进行校验,才能获取验证成功的数据或保存成模型类对象
data = {
'name':"张三",
...
}
ser = Serializer(data=data)
if ser.is_valid():
ser.save() # 只传 data 参数的时候,save 方法会触发序列化器器中的 create 方法
比如现在,还是之前练习需要提交数据创建课程的接口,此时可以这么做
为了能够保证数据成功入库,默认的普通序列化器是不具备入库功能的,需要编写***create***方法
class CourseSer(serializers.Serializer):
name = serializers.CharField(max_length=20)
created = serializers.DateField()
def create(self, validated_data):
object = Course.objects.create(
**validated_data
)
return object
成功之后,就可以通过像之前一样的数据提交,编写视图完成数据入库,序列化器可以直接处理***request***所提交的数据***data***,并且可以剔除在**request.data中其他多余的字段,只会处理序列化器里的字段
class CourseCreate(APIView):
def post(self, request):
ser = CourseSer(data=request.data)
if ser.is_valid():
ser.save()
error = ser.errors
return Response({'msg': error if error else 'success'})
反序列化经过校验的数据,不光可以创建数据,还可以更新数据呢
默认普通序列化器是没有自带对于数据的更新方法的,现在需要在序列化器里创建***update***方法
class CourseSer(serializers.Serializer):
name = serializers.CharField(max_length=20)
created = serializers.DateField()
def update(self, instance, validated_data):
# instance 要更新的数据,validated_data 是新数据
instance.name = validated_data.get('name', instance.name)
instance.type = validated_data.get('create', instance.type)
instance.save()
return instance
然后通过PUT传递要更新数据的ID,以及更新后的值,来为某条数据更新
class CourseUpdate(APIView):
def put(self, request):
id_ = request.data.get("id") # 获取当前更新数据的 ID
try:
course = Course.objects.get(pk=id_)
except Course.DoesNotExist:
return Response({'msg': '更新失败,不存在这条数据'})
ser = CourseSer(instance=course, data=request.data)
if ser.is_valid():
ser.save()
error = ser.errors
return Response({'msg': error if error else 'success'})
之前的序列化器,很明显可以感觉到,如果模型类字段少了,还行,但是模型字段越来越多,那么开发者在序列化器里所要复刻的字段也要越来越多,很麻烦奥
而且还得手动实现***update***和**create方法,而且光写了序列化器字段还不行,还得有字段属性
于是乎,有了现在的与模型类关联的序列化器,可以更加方便的进行字段映射以及内置方法的编写,简直是太棒了
模型类关联序列化器大概总结有如下三个特性,一个缺点
那么模型类关联的序列化器用啥呢?用的是新的序列化器基类
from rest_framework.serializers import ModelSerializer
比如一个商品模型类
class Goods(models.Model):
title = models.CharField(max_length=200, verbose_name='商品标题')
description = models.TextField(verbose_name='描述')
inventory = models.IntegerField(default=0, verbose_name='库存量')
price = models.DecimalField(
max_digits=10, decimal_places=2, verbose_name='商品价格')
cover = models.CharField(max_length=200, verbose_name='封面图')
issale = models.BooleanField(default=False, verbose_name='是否促销')
saleprice = models.DecimalField(
max_digits=10, decimal_places=2, verbose_name='促销价格')
ishow = models.BooleanField(default=True,verbose_name='是否上架')
createtime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
def __str__(self):
return self.title
class Meta:
db_table = 'goods'
按照之前的普通序列化写法,你需要同步一个字段,并将字段属性也要记得同步,非常麻烦
但通过与模型类关联的序列化器就很简单了
class GoodsSer(serializers.ModelSerializer):
class Meta:
model = Goods
fields = '__all__' # 指明所有模型类字段
# exclude = ('createtime',) # 排除掉的字段
# read_only_fields = ('title','description') # 只用于序列化的字段
# fields = ('title','description','inventory') # 手动指明字段
# extra_kwargs = {
# 'price':{'min_value':0, 'required':True},
# } # 修改原有字段的选项参数
模型类关联的序列化器和普通的序列化器使用方法一样
使用序列化器返回当前所有的商品数据,还是像之前一样传入**instance参数即可,还要记得由于是多个商品,不是单独数据,要记得加many=True参数
模型序列化器的创建就更简单了,不需要手动实现***create***方法,大致流程如下:
创建商品接口
class GoodsCreate(APIView):
def post(self, request):
ser = GoodsSer(data=request.data)
if ser.is_valid():
ser.save()
error = ser.errors
return Response({'msg': error if error else 'success'})
注意:反序列化自动生成的字段属性中,不会包含原始模型类字段中的***default***字段属性
更新某一个商品数据,模型序列化器也是自带了***update***方法
更细商品接口
class GoodsUpdate(APIView):
def put(self, request):
id_ = request.data.get("id")
try:
goods = Goods.objects.get(pk=id_)
except Goods.DoesNotExist:
return Response({'msg': '更新失败,不存在这条数据'})
ser = GoodsSer(instance=goods, data=request.data)
if ser.is_valid():
ser.save()
error = ser.errors
return Response({'msg': error if error else 'success'})