序列化组件
序列化组件
序列化介绍
作用:
- 序列化,序列化器(类)会把模型对象(Book对象,Queryset对象)转换成字典,经过response以后变成json字符串
- 反序列化,把客户端发送过来的数据,经过request以后变成字典(request.data),序列化器(类)可以把字典转成模型
- 反序列化,完成数据校验功能
本质:
就是写一个类,继承一个基类
可以完成序列化,反序列化和数据校验
序列化Serializer类的使用
1 视图类
### 序列化器的使用
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Books
from rest_framework.request import Request
from .serizlizer import BookSerializer
class BookAPIView(APIView):
#查询所有接口
def get(self, request, *args, **kwargs):
book_list=Books.objects.all()
# 序列化过程,把queryset转成字典
# 第一个参数是要序列化的对象,如果序列化多条数据,一定要加上many=True
ser=BookSerializer(instance=book_list,many=True)
print(ser.data)
return Response(ser.data)
def post(self, request, *args, **kwargs):
ser=BookSerializer(data=request.data) #新增,不用传instance
if ser.is_valid():
ser.save()
return Response(ser.data)
class BookDetailAPIView(APIView):
# 查询单个
def get(self, request, pk):
book = Books.objects.filter(pk=pk).first()
# 序列化过程,把Book转成字典
# 第一个参数是要序列化的对象,如果序列化多条数据
ser = BookSerializer(instance=book)
print(ser.data)
return Response(ser.data)
def delete(self,request,pk):
Books.objects.filter(pk=pk).delete()
return Response()
def put(self,request,pk):
book=Books.objects.filter(pk=pk).first()
# 反序列化,修改
# instance 传要修改的对象
ser=BookSerializer(instance=book,data=request.data) #修改
# 校验数据
if ser.is_valid():
ser.save() # 报错
return Response(ser.data)
2 序列化类
from rest_framework import serializers
from .models import Books
class BookSerializer(serializers.Serializer):
#写字段(要序列化,反序列化的字段)
name=serializers.CharField()
price=serializers.IntegerField()
publish=serializers.CharField()
# 如果要更新,一定要重写update方法
def update(self, instance, validated_data):
# 修改
instance.name=validated_data.get('name')
instance.price=validated_data.get('price')
instance.publish=validated_data.get('publish')
# 保存
instance.save()
# 返回
return instance
# 如果要新增,一定要重写create方法
def create(self, validated_data):
# 保存
book=Books.objects.create(**validated_data)
# 一定记得return
return book
3 路由
urlpatterns = [
# drf继承APIView的路由
path('books/', views.BookAPIView.as_view()),
path('books/<int:pk>', views.BookDetailAPIView.as_view()),
]
4 模型
class Books(models.Model):
name=models.CharField(max_length=32)
price=models.IntegerField()
publish=models.CharField(max_length=32)
serializer高级使用
1 source参数
- 指定对应模型的字段或方法(表模型中写的方法,方法返回的结果就是这个字段的值)
- book_name=serializers.CharField(source="name")
2 给字段加自己的校验规则
- name=serializers.CharField(max_length=8,min_length=3)
3 SerializerMethodField
- 在序列化中写方法,使其返回结果映射个对应的字段
publish=serializers.SerializerMethodField()
def get_publish(self,obj):
return {'name':obj.publish.name,'addr':obj.publish.addr}
4 局部钩子
def validate_name(self,name):
if name.startswith('sb'):
raise ValidationError('不能以sb开头')
else:
return name
5 全局钩子
def validate(self, attrs):
print(attrs.get('name'))
print(attrs.get('addr'))
return attrs
serializer在映射表字段时没有指定的表,而ModelSerializer的类与表有一一对应,所以在用serializer类写修改表数据和添加表数据时要重写create,update方法
序列化类如果传了instance,调用save方法触发update,否则触发create
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
else:
self.instance = self.create(validated_data)
class PublishSerializer(serializers.Serializer):
name=serializers.CharField(max_length=8,min_length=3)
addr=serializers.CharField(max_length=8,min_length=3)
def validate_name(self,name):
if name.startswith('sb'):
raise ValidationError('不能以sb开头')
else:
return name
def validate(self, attrs):
name=attrs.get('name')
print(name)
addr=attrs.get('addr')
print(addr)
return attrs
def create(self, validated_data):
# 保存
publish=Publish.objects.create(**validated_data)
# 一定记得return
return publish
ModelSerializer使用
1 继承ModelSerializer
- class PublishModelSerializer(serializers.ModelSerializer):
2 字段通过表模型映射
class Meta:
model = Pubilsh # 指定对应的表(model不能改成其他名字)
fields = '__all__' # 序列化所有字段
fields = ['id', 'name', 'addr'] # 序列化指定字段,可以加上方法
exclude = ['id'] # 将某些字段排除,不能与dields一起使用
# depth = 1 # 指定映射深度,外键关联的深度,1表示一层外键表,一般不用
3 反序列化时,字段自己的校验规则映射了表模型的
4 可以重写字段来改变规则
5 可以扩写字段(表模型中没有的字段)
6 局部钩子和全局钩子和Serializer一样使用
7 wirte_only和read_only参数
# 该字段反序列化时候使用, 序列化时候不用
# name=serializers.CharField(write_only=True)
# 该字段序列化的时候使用,反序列化不用 (字段没写可为空会存不进去)
# name=serializers.CharField(read_only=True)
8 extra_kwargs
class Meta:
model = Pubilsh
fields = ['id', 'name', 'addr']
extra_kwargs={'name':{'write_only':True,'max_length':8}}
# 额外给字段传递参数,类似于重写字段:
# name = serializers.CharField(write_only=True,'max_length':8)
字段和参数补充
常用字段
| 字段 | 字段构造方式 |
|---|---|
| CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
| IntegerField | IntegerField(max_value=None, min_value=None) |
| DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
| DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
| TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
| BooleanField | BooleanField() |
| DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
| NullBooleanField | NullBooleanField() |
| EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
| RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
| SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ |
| URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
| 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" |
| IPAddressField | IPAddressField(protocol=’both’, unpack_ipv4=False, **options) |
| FloatField | FloatField(max_value=None, min_value=None) |
| DurationField | DurationField() |
| ChoiceField | ChoiceField(choices) choices与Django的用法相同 |
| MultipleChoiceField | MultipleChoiceField(choices) |
| FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| 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=) |
指定参数
| 参数名称 | 作用 |
|---|---|
| max_length | 最大长度 |
| min_lenght | 最小长度 |
| allow_blank | 是否允许为空,传值时可不穿 |
| trim_whitespace | 是否截断空白字符 |
| max_value | 最小值 |
| min_value | 最大值 |
通用参数
| 参数名称 | 说明 |
|---|---|
| read_only | 表明该字段仅用于序列化输出,默认False |
| write_only | 表明该字段仅用于反序列化输入,默认False |
| required | 表明该字段在反序列化时必须输入,默认True |
| default | 反序列化时使用的默认值 |
| allow_null | 表明该字段是否允许传入None,默认False |
| validators | 该字段使用的验证器 |
| error_messages | 包含错误编号与错误信息的字典 |
| label | 用于HTML展示API页面时,显示的字段名称 |
| help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 |
钩子函数的源码分析
# 入口是 ser.is_valid(),是BaseSerializer的方法
# 最核心的代码
self._validated_data = self.run_validation(self.initial_data) # 切记不要按住ctrl点
# run_validation 调用的是Serializer类的方法
def run_validation(self, data=empty):
value = self.to_internal_value(data) # 局部钩子的代码
try:
self.run_validators(value)
value = self.validate(value) # 全局钩子的执行
assert value is not None, '.validate() should return the validated data'
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value
# 局部钩子核心代码
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None) #反射字段的局部钩子方法
try:
if validate_method is not None:
validated_value = validate_method(validated_value) #执行局部钩子方法
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
序列化组件部分源码分析
# 1 对象的实例化过程,__new__在__init__之前执行,new是造对象,init是初始化对象
# 2 序列化类在实例化的时候,先调用的是BaseSerializer中的__new__
def __new__(cls, *args, **kwargs):
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs) ##实例化出ListSerializer的对象
return super().__new__(cls, *args, **kwargs) # 实例化出自己的对象
def many_init(cls, *args, **kwargs):
return list_serializer_class(*args, **list_kwargs)
# 3 ListSerializer 和BookSerializer有什么联系
- ListSerializer类似于列表一样包括了多个BaseSerializer,但其本身不是列表
-[ser1,ser2,ser3]

浙公网安备 33010602011771号