drf
第一章 django web开发模式、api接口、api接口测试工具、restful规范、序列化反序列化、drf安装使用
第二章 drf的使用、APIView源码分析、Request源码分析、Serializer的序列化
第三章 Serializer的反序列化、字段与参数、局部与全局钩子、ModelSerializer使用
使用serializer序列化器时,反序列化一般针对update和create,所以如果有对应表主键时最好为其设置read_only为True
表中无外间关系时可以使用serializer或者ModelSerializer
此处展示Serializer使用方式
表关系:
class Book(models.Model):
bname = models.CharField(max_length=20, verbose_name='书籍名称')
price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='书籍单价')
def __str__(self):
return self.bname
对应的Serializer序列化器
针对于Serializer创建与更新方法需要重写,删除、查询、查询单个需要在视图类中完成
class BookSerializer(serializers.Serializer):
bname = serializers.CharField(max_length=20)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
def update(self, instance, validated_data):
instance.bname = validated_data.get('bname')
instance.price = validated_data.get('price')
instance.save()
return instance
def create(self, validated_data):
book_obj = Book.objects.create(**validated_data)
return book_obj
对应视图类
class BookApiView(views.APIView):
def get(self,request):
dict = {{'code':200, 'msg':'查询成功成功'}}
if not request.query_params:
books = Book.objects.all()
dict['msg'] = '查询全部书籍成功'
else :
books = Book.objects.filter(pk=request.query_params.get('id'))
dict['msg'] = '查询一本书籍成功'
bookSerializer = BookSerializer(instance=books, many=True)
dict['data'] = bookSerializer.data
return Response(dict)
def delete(self,request):
dict = {'code':200}
pk = request.data.get('id')
if pk:
book_obj = Book.objects.filter(pk=pk)
if book_obj:
book_obj.delete()
dict['msg'] = '删除成功'
dict['data'] = ''
else :
dict['code'] = 10003
dict['msg'] = '该书不存在,无法删除'
else:
dict['code'] = 10004
dict['msg'] = '请指定书籍id'
return Response(dict)
def put(self,request):
dict = {'code': 200}
book_obj = Book.objects.filter(pk=request.data.get('id')).first()
if book_obj:
bookSerializer = BookSerializer(instance=book_obj, data=request.data)
if bookSerializer.is_valid():
bookSerializer.save()
dict['msg'] = '修改成功'
dict['data'] = bookSerializer.data
else:
dict['code'] = 10001
dict['msg'] = '修改失败,数据未通过验证'
dict['errors'] = bookSerializer.errors
else:
dict['code'] = 10002
dict['msg'] = '不存在该书籍'
dict['errors'] = '找不到对应的书籍id'
return Response(dict)
def post(self,request):
print(request.FILES)
dict = {'code': 200}
bookSerializer = BookSerializer(data=request.data)
if bookSerializer.is_valid():
bookSerializer.save()
dict['msg'] = '创建成功'
dict['data'] = bookSerializer.data
else:
dict['code'] = 10005
dict['msg'] = '数据验证未通过'
dict['errors'] = bookSerializer.errors
return Response(dict)
常见字段与models基本一致
常用参数:
read_only:True 不设置时默认为False 作用是只在序列化时产生该字段数据
write_only:True 不设置时默认为False 作用是只在反序列化时需要该字段数据
error_messages 设置该字段检验不通过的错误信息
depth 连表查询深度
局部钩子是重写validate_字段名 函数
需要抛出错误时使用ValidationError
通过验证时返回对应的字段
def validate_pname(self, pname):
if re.findall('京东', pname):
raise ValidationError('出版社名字不能包含京东')
else:
return pname
全局钩子是重写validate函数 在全局钩子中attrs是对应序列化器中的所有字段
需要抛出错误时使用ValidationError
通过验证时返回对应的attrs
def validate(self, attrs):
if re.findall('日本', attrs.get('address')):
raise ValidationError('出版社地址不能在日本')
return attrs
modelSerializer是model与serializer的结合,在ModelSerializer中我们只需要配置好对应的字段和其参数即可,不需要重写update和create方法,ModeSerializer会自动完成增删改查操作。
models.py
class Book(models.Model):
bid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name
ModelSerializer序列化器
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book # 此处设置ModelSerializer所关联的表
# 此处有俩种设置方法
fields = '__all__' #方法1使用__all__会自动匹配models中的所有字段
fields = ['bid', 'name', 'price', 'publish', 'authors', 'publish_read', 'authors_read'] #方法2使用列表的形式将需要对应的字段填入
extra_kwargs = {
'bid': {'read_only':True},
'publish': {'write_only': True},
'authors': {'write_only': True},
} # 对自动对应的字段进行Serializer进行参数设置,此时的Serializer字段名与models中一致
针对于外键字段可以使用三种方式进行反序列化(序列化由ModelSerializer自动完成)
第一种,构建虚拟字段为反序列化提供外键字段的查询结果(此方法不推荐)
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book # 此处设置ModelSerializer所关联的表
# 此处有俩种设置方法
fields = '__all__' #方法1使用__all__会自动匹配models中的所有字段,之后再新建虚拟字段
fields = ['bid', 'name', 'price', 'publish', 'authors', 'publish_read', 'authors_read'] #方法2使用列表的形式将需要对应的字段填入包括虚拟字段,之后再对虚拟字段进行重新设置
# fields选择一种即可
extra_kwargs = {
'bid': {'read_only':True}, #反序列化时主键一般都会设置read_only
} # 对自动对应的字段进行Serializer进行参数设置,此时的Serializer字段名与models中一致
#在从此处创建虚拟字段,注意虚拟字段为class BookSerializer的属性(注意缩进)
publish_read = serializers.SerializerMethodField(read_only=True) #虚拟字段名可随意设置,不要忘记设置read_only
authors_read = serializers.SerializerMethodField(read_only=True)
#虚拟字段设置完毕后需要生成对应虚拟字段取值方法
def get_publish_read(self, book): # 此处方法名必须为get_虚拟字段名,参数self为serializer类,book可以自由设置名称该参数为对应的表对象
return book.publish.name #返回值依据外键关系来获取最好为query_set,一对多时需要返回query_set,一对一是也得返回query_set区别是一对一的query_set中只有一个字典
# 针对于多对多字段需要循环处理
def get_authors_read(self, book):# 由于是多对多关系此时的book为一个query_set其中包含多个表对象
authors_list = []
for author in book.authors.all():
authors_list.append({'aid':author.pk, 'name':author.name, 'age':author.age, 'address':author.author_detail.address})
return authors_list
第二种拔插式虚拟字段设置
ModelSerializer序列化器:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = ['bid', 'name', 'price', 'publish', 'authors', 'publish_read', 'authors_read'] #此处需要将方法名与虚拟字段名对应起来,不可以使用__all__
extra_kwargs = {
'bid': {'read_only':True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
models模型:
class Book(models.Model):
bid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name
@property # 当fields选择第一种是需要添加该装饰器 装饰器作用是将类方法变为类属性
def publish_read(self):
return {'name':self.publish.name,'email':self.publish.email}
@property
def authors_read(self):
authors_read=[]
for author in self.authors.all():
authors_read.append({'name':author.name,'address':author.author_detail.address})
return authors_read
第三种设置连表深度
连表查询深度:
就是连表次数的设置
例如:
作者表与出版社表为一对多关系,从作者表可以连表查询到对应的出版社信息 此时深度为1
出版社表与图书表为一对多关系,从出版社连表查询对应的图书,此时深度为2
…后续按照此进行
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = ['bid', 'name', 'price', 'publish', 'authors']
depth = 1 # 官方建议不要超过10,实际上最好不要超过3
extra_kwargs = {
'bid': {'read_only':True},
}