目录
序列化常用字段和字段参数-souce-定制字段的两种方式-多表关联反序列化保存-反序列化字段校验及其他-ModelSerializer使用
昨日回顾
# 1 APIView---> drf提供的 继承了原来的View 以后写视图类 都继承APIView及其子类
# 2 APIView执行流程
-1 去除了csrf认证
-2 包装了新的Request对象
-用起来跟之前一样---> 因为__getattr__ 反射了请求方式的校验
-request.data---> put,post,get,delete...请求体中携带的数据 无论什么编码 都是字典
-request.query_params---> 老的request.GET
-request.FILES---> 跟之前一样 重写了文件类
-3 执行了三大认证(认证 权限 频率)---> 在执行视图类的方法之前执行
-4 三大认证的代码 视图类方法的代码 如果除了异常 会有异常捕获---> 后期会做统一处理
# 3 Request源码分析
# 序列化类---> APIView+序列化类+Response---> 五个接口
-序列化类的作用:做序列化 反序列化 反序列化校验
-序列化过程:
-序列化类 继承Serializer 写字段CharField 表示要序列化和反序列化的字段
-视图类中:单个对象序列化 传入instance参数 多个qs对象 要传many=True
-序列化类对象:ser.data---> 字典或列表---> Resonse---> Json格式字符给前端
-序列化单条和多条 路由不一样 写成两个视图类 分别两个get方法
-反序列化过程:新增 修改
-新增:
-前端无论什么编码格式 都在request.data中 是字典
-request.data:
-urlencoded form-data QueryDict
-json---> dict
-拿到前端传入的数据 进行反序列化---> 序列化类的反序列化 完成
-序列化类得到对象 传入参数 data=request.data
-校验数据
-保存:ser.save()---> 序列化类中重写create方法
-修改:
-拿到前端传入的数据 进行反序列化 查出要修改的对象---> 序列化类的反序列化 完成
-序列化类得到对象 传入参数 instance=要修改的对象 data=request.data
-校验数据
-保存:ser.save()---> 序列化类中重写update方法
# 4 反序列化类的校验
-只要在序列化类中写局部和全局钩子
-局部钩子
def validate_字段名(self, name):
校验通过,返回name
如果不通过,抛出异常
-全局钩子
# attr 前端传入的数据 走完局部钩子校验后的数据
def validate(self, attrs):
校验通过 返回attrs
如果不通过 抛出异常
作业
# 原生的django的request中没有data
def outer(func):
# 通过装饰器做 装饰器视图函数的 以后都会有request
def inner(request, *args, **kwargs):
# 造个新的request
# 如果是 urlencoded form-data---> request.POST就有值
# 如果request.POST 就没有值 就是json格式编码
try:
# 如果是json格式编码,就解码成字典,如果不是走异常
request.data = json.loads(request.body)
except Exception as e:
request.data = request.POST
res = func(request, *args, **kwargs)
return res
return inner
@outer
def test(request):
print(request.POST)
print(request.data)
return HttpResponse('ok')
# 总结:前端提交数据的编码格式
-urlencoded:
name=lqz&age=19&price=999 放在了请求体中
-formdata:分数据部分和文件部分
-json格式:{"name": "lqz", "age": 19}
今日内容概要
-
1 序列化类常用字段和字段参数(了解)
- 1.1 常用字段类
- 1.2 常用字段参数
-
2 序列化高级用法之source(了解)
- 2.1 序列化定制字段名字
-
3 序列化高级用法之定制字段的两种方式
- 3.1 SerializerMethodField定制
- 3.2 在表模型中定制
-
4 多表关联反序列化保存
- 4.1 新增图书接口
- 4.2 修改图书接口
-
5 反序列化字段校验其他
-
6 ModelSerializer使用
今日内容详细
1 序列化类常用字段和字段参数(了解)
# 序列化类---> 字段类 CharField 除此之外还有哪些其他的
# 序列化类---> 字段类 字段类上 传属性的 序列化类上 也可以写属性
【models.CharField(max_length=32)】
1.1 常用字段类
#1 BooleanField BooleanField()
#2 NullBooleanField NullBooleanField()
#3 CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
#4 EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
#5 RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
#6 SlugField SlugField(max_length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
#7 URLField URLField(max_length=200, min_length=None, allow_blank=False)
#8 UUIDField UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
#9 IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
#10 IntegerField IntegerField(max_value=None, min_value=None)
#11 FloatField FloatField(max_value=None, min_value=None)
#12 DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
#13 DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
#14 DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
#15 TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
#16 DurationField DurationField()
#17 ChoiceField ChoiceField(choices) choices与Django的用法相同
#18 MultipleChoiceField MultipleChoiceField(choices)
#19 FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
#20 ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
-----------重要 后面讲-------------
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)
# 记住的:CharField IntegerField DecimalField DateTimeField BooleanField
ListField
DictField
1.2 常用字段参数
选项参数:
# CharField及其子类的(EmailField)---> 反序列化的校验 字段自己的规则
max_length 最大长度
min_length 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
# IntegerField
max_value 最小值
min_value 最大值
# 所有字段类都有的
required 表明该字段在反序列化时必须输入 默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None 默认False
validators 该字段使用的验证器
-----看一眼可以忘掉-----
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面是显示的子弹名称
help_text 用于HTML展示API页面时 显示的字段帮助提示信息
# 重点:
read_only 表明该字段仅用于序列化输出 默认False
write_only 表明该字段仅用于反序列化输入 默认False
# 反序列化校验执行流程
-1 先执行字段自己的校验规则---> 最大长度 最小长度 是否为空 是否必填 最小数字......
-2 validators[方法,]---> 单独给这个字段加校验规则
name=serializers.CharField(validators=[方法,])
-3 局部钩子校验规则
-4 全局钩子校验规则
2 序列化高级用法之source(了解)
# 创建关联表
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
address = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11)
# 重点:source可以指定序列化字段的名字
from rest_framework import serializers
# 序列化类
class BookSerializer(serializers.Serializer):
# 字段参数 通用的 所有子段都可以写 通过source指定哪个字段
# 自有字段 直接写字段名字
real_name = serializers.CharField(source='name')
real_price = serializers.CharField(source='price')
# 关联字段 一对多的关联 直接点
publish = serializers.CharField(source='publish.name')
# 多对多 source不能用
authors = serializers.CharField(source='authors.all')
3 序列化高级用法之定制字段的两种方式
3.1 SerializerMethodField定制
# 定制关联字段的显示形式
-一对多的 显示字典
-多对多 显示列表套字典
# 定制序列化的代码
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 定制返回格式一---> 方式一:利用SerializerMethodField
publish_detail = serializers.SerializerMethodField()
def get_publish_detail(self, obj):
return {'name': obj.publish.name, 'address': obj.publish.address}
author_list = serializers.SerializerMethodField()
def get_author_list(self, obj):
l1 = []
for author in obj.authors.all():
l1.append({'name': author.name, 'phone': author.phone})
return l1
3.2 在表模型中定制
# models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def publish_detail(self):
return {'name': self.publish.name, 'address': self.publish.address}
def author_list(self):
l1 = []
for author in self.authors.all():
l1.append({'name': author.name, 'phone': author.phone})
return l1
# serializer序列化类
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# publish_detail = serializers.CharField() # 拿到字符串格式
publish_detail = serializers.DictField() # 拿到字典格式
author_list = serializers.ListField()
4 多表关联反序列化保存
4.1 新增图书接口
# 新增图书接口
-前端传入的数据格式:{"name": "红楼梦", "price": 555, "publish": 1, "authors": [1,2]}
# views
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 10000, 'msg': '新增成功'})
else:
return Response({'code': 10001, 'msg': ser.errors})
# serializer序列化类
class BookSerializer(serializers.Serializer):
# name和price 既用来序列化 又用来反序列化 既写又读 不用加read_only write_only
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 这两个做序列化使用,只读read_only
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
# 这两个做反序列化使用,只写write_only
publish = serializers.CharField(write_only=True)
authors = serializers.ListField(write_only=True)
# 新增重写create方法
def create(self, validated_data):
# validated_data 校验过后的数据
# 新增一本图书写入数据库并且拿到该书本对象
book = Book.objects.create(name=validated_data.get('name'), price=validated_data.get('price'), publish_id=validated_data.get('publish'))
# 作者也要关联
# book.authors add remove set clear......
book.authors.add(*validated_data.get('authors'))
return book
4.2 修改图书接口
# views
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data, instance=book)
if ser.is_valid():
ser.save()
return Response({'code': 10000, 'msg': '修改成功'})
else:
return Response({'code': 10001, 'msg': ser.errors})
# serializer序列化类
# 修改需要重写update
def update(self, instance, validated_data):
# validated_data通过验证的前端传入数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish_id = validated_data.get('publish')
authors = validated_data.get('authors')
# 先清空再add
instance.authors.clear()
instance.authors.add(*authors)
instance.save()
return instance
5 反序列化字段校验其他
# 4c层
-1 字段自己的:举例:name = serializers.CharField(max_length=8, error_messages={'max_length': '太长了'})
-2 validators=[方法,] 忽略掉,很少人用
-3 局部钩子
-4 全局钩子
6 ModelSerializer使用
# ModelSerializer 继承自Serializer 帮咱们完成了很多操作
-跟表模型强关联
-大部分请求 不用写create和update了
# 如何使用
# ModelSerializer的使用
# ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book # 跟book表建立了关系 序列化类和表模型类
# fields = '__all__' # 序列化了所有Book中的字段
# 序列化指定的字段,
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
# 定制字段反序列化时 给字段类加属性---> 方式一
extra_kwargs = {
'name': {'max_length': 8},
'price': {'max_length': 32},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
# 局部钩子和全局钩子跟之前完全一样
def validate_name(self, name):
if name.startwith('sb'):
raise ValidationError('不能sb')
else:
return name
"""
# 如果Meta写了__all__ ,就相当于,复制了表模型中的所有字段,放在了这里,做了个映射
# name = serializers.CharField(max_length=32)
# price = serializers.CharField(max_length=32)
# 定制name反序列化时,最长不能超过8 给字段类加属性---方式二,重写name字段
# name = serializers.CharField(max_length=8)
# 同理,所有的read_only和wirte_only都可以通过重写或使用extra_kwargs传入
# 终极,把这个序列化类写成跟之前一模一样项目
# publish_detail = serializers.SerializerMethodField(read_only=True)
# def get_publish_detail(self, obj):
# return {'name': obj.publish.name, 'addr': obj.publish.addr}
# author_list = serializers.SerializerMethodField(read_only=True)
# def get_author_list(self, obj):
# l = []
# for author in obj.authors.all():
# l.append({'name': author.name, 'phone': author.phone})
# return l
"""
标签:多表,name,max,length,常用字,CharField,serializers,序列化
From: https://www.cnblogs.com/zpf1107/p/17087458.html