本篇重点介绍 DRF 序列化器基础使用方法,并带有一个演示案例。
序列化 序列化器会将模型类对象转化为字典,response
后变成 json
字符串。
反序列化 把客户发送过来的数据, request
后变成字典,序列化器可以将字典转成模型,同时校验客户发送数据的合法性。
序列化器(类) 开发者定义的一个实现序列化和反序列化的类。
模型序列化器(类) 一种对应 Django
模型的序列化器。
序列化器基类 DRF
中所有的序列化器类都必须继承于序列化器基类(rest_framework.serializers.Serializer
) 。
模型序列化器基类 序列化器基类的子类,同时 DRF
中所有的序列化器类都必须继承于 rest_framework.serializers.ModelSerializer
。
一个完整序列化器中应该包含三方面的内容:
客户端字段 = serializer.字段类型(字段校验项=字段值)
如果当前序列化器为模型序列化器,则需要声明调用的模型信息
# serializer.py
from rest_framework import serializers
class TestModelSerializer(serializers.ModelSerializer):
class Meta:
model = 模型
fields = 字段列表
验证字段合法性之后必须要将值返回(原值或者修改过的值)
重写 create()
和 update()
两个方法,实现数据的插入和更新。
添加数据操作,添加数据以后,自动实现从字典变成模型对象的过程。
更新数据操作,添加数据以后,自动实现从字典变成模型对象的过程。
TestSerializer(instance=None,data=empty,**kwargs)
用于序列化时,将模型类对象传入 instance
参数;
用于反序列化时,将要被反序列化的数据传入 data
参数;
除了 instance
和 data
参数外,在构造 Serializer
对象时,还可以通过 context
参数额外添加数据,通过 context
添加的数据,可以通过 Serializer
对象的 context
属性获取;
数据校验的方法:
自定义报错信息,在字段选项中添加选项 error_messages
class TestSerializer(serializers.Serializer):
def validate_<字段名>(self,value):
pass
return value
class TestSerializer(serializers.Serializer):
def validate(self,attrs):
pass
return attrs
# serializer.py
from rest_framework import serializers
class TestSerializer(serializers.Serializer):
def create(self,validated_data):
pass
def update(self,instance,validate_data):
pass
# models.py
class Student(models.Model):
name = models.CharField(
null=False,
max_length=255,
verbose_name='姓名'
)
age = models.IntegerField(
null=False,
verbose_name='年龄'
)
sex = models.IntegerField(
null=False,
verbose_name='性别'
)
active = models.BooleanField(
# 默认值为 True
default=True,
verbose_name='是否活跃'
)
description = models.CharField(
max_length=255,
null=True,
blank=True,
verbose_name='描述'
)
date_joined = models.DateTimeField(
default=timezone.now,
verbose_name='加入时间'
)
# urls.py
from django.urls import path
from .views import StudentView
urlpatterns = [
path('student/' , StudentView.as_view()),
]
views.py
中视图函数(使用 DRF)
# views.py
from rest_framework.views import APIView
from django.http import JsonResponse
from SerializerDemo.models import Student
from SerializerDemo.serializers import StudentSerializer
class StudentView(APIView):
def get(self, request, pk):
"""
序列化器,序列化阶段的调用
"""
if pk == 'all':
# 1、获取数据集
student_list = Student.objects.all()
# 2、实例化序列化器,得到序列化对象
serializer = StudentSerializer(instance=student_list, many=True)
# 3、调用序列化对象的data属性方法获取转换后的数据
data = serializer.data
# 4、响应数据
return JsonResponse({'data': data, 'message': 'success'})
else:
query = Student.objects.filter(id=pk)
if query.count():
student = query.first()
serializer = StudentSerializer(instance=student)
data = serializer.data
return JsonResponse({'data': data, 'message': 'success'})
else:
return JsonResponse({'message': 'ID不存在'})
# serializers.py
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
"""
完整的序列化类内部包含三部分的内容
1、序列化转换的字段声明
2、反序列化的校验器,即校验前端传入的字段
3、反序列化模型操作的方法,create和update方法
"""
id = serializers.IntegerField()
date_joined = serializers.DateTimeField()
name = serializers.CharField()
age = serializers.IntegerField()
active = serializers.BooleanField()
sex = serializers.IntegerField()
description = serializers.CharField()
def update(self, instance, validated_data):
pass
def create(self, validated_data):
pass
# views.py
from rest_framework.views import APIView
from django.http import JsonResponse
from SerializerDemo.models import Student
from SerializerDemo.serializers import StudentSerializer
import json
class StudentView(APIView):
def post(self, request):
"""反序列化,采用字段选项来验证数据"""
# 1、接收客户端提交的数据
# 1.1 实例化序列化器,获取序列化对象
data = json.dumps(request.body)
# 1.2 调用序列化对象验证数据
serializer = StudentSerializer(data=data)
# 1.3 获取验证结果
serializer.is_valid() # 不抛出异常
serializer.is_valid(raise_exception=True) # 抛出异常
# 2、操作数据
pass
# 3、返回数据
return JsonResponse(serializer.validated_data)
def put(self, request):
"""反序列化,采用字段选项来验证数据"""
# 1、根据客户端提交的数据获取指定数据
# 1.1 实例化序列化器,获取序列化对象
pk = request.data.get('id', '')
student = Student.objects.filter(pk=pk).first()
data = json.dumps(request.body)
# 1.2 调用序列化对象验证数据
serializer = StudentSerializer(instance=student, data=data)
# 1.3 获取验证结果
serializer.is_valid(raise_exception=True) # 抛出异常
# 2、操作数据
# 会根据实例化序列化器的时候是否传入instance属性来自动调用create或者update方法,如果传入instance属性,调用update方法,没有传入instance属性,调用create方法
serializer.save()
# 3、返回数据
return JsonResponse(serializer.data)
def check_sex(value):
"""
外部校验器 validator
"""
if value not in [0, 1, 2]:
raise serializers.ValidationError(
detail='性别设置错误',
code='check_sex'
)
return value
class StudentSerializer(serializers.Serializer):
"""
完整的序列化类内部包含三部分的内容
1、序列化转换的字段声明
2、反序列化的校验器,即校验前端传入的字段
3、反序列化模型操作的方法,create和update方法
"""
# read_only=True,在客户端提交数据[反序列化阶段]不要求的字段
id = serializers.IntegerField(read_only=True)
date_joined = serializers.DateTimeField(read_only=True)
# required=True,反序列化阶段必填
name = serializers.CharField(required=True)
# 最大值 max_value 和最小值 min_value
age = serializers.IntegerField(
max_value=100,
min_value=0,
error_messages={
"min_value": "Age must older than 0",
"max_value": "Age must younger than 100"
}
)
# 默认值为 True
active = serializers.BooleanField(default=True)
# validator的值为列表,列表的成员为函数名,而不是函数的调用
sex = serializers.IntegerField(validators=[check_sex])
# 允许客户端不填写内容(None),或者值为 ""
description = serializers.CharField(allow_null=True, allow_blank=True)
def validate_name(self, data):
"""
校验单个字段
方法名必须以validate_<字段名>为名称,否则序列化器无法识别
validate开头的方法,会自动被is_valid调用
"""
if data in ["管理员", "超级管理员"]:
raise serializers.ValidationError(
detail="学生名字不能是管理员或者超级管理员",
code="name"
)
return data
def validate(self, attrs):
"""
验证来自客户端的所有字段
"""
if not attrs['active'] and attrs['description']:
raise serializers.ValidationError(
detail='非active学生需要添加描述',
code='validate'
)
return attrs
def update(self, instance, validated_data):
"""
参数都是固定的,
instance 实例化序列化器对象时,必须要传入的模型对象
"""
for key, value in validated_data.items():
setattr(instance, key, value)
instance.save()
return instance
def create(self, validated_data):
"""
保存数据
"""
student = Student.objects.create(**validated_data)
return student
在对序列化器进行 save()
保存时,可以额外传递数据,这些数据可以在 create()
和 update()
中的 validated_data
参数中获取到
serializer.save(owner=request.user)
默认序列化器必须传递所有的 required
字段,否则会抛出校验异常,但是可以使用 partial
参数来允许部分字段更新
更新 name
,不需要校验其他字段,可以设置 partial=True
serializer = StudentSerializer(student,data={'name':'xiaodong'},partial=True)