066.Python框架DRF之序列化器Serializer
一 序列化器-Serializer
作用:
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
1.1 定义序列化器
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。
1.1.1 创建一个ser的app
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# python3 manage.py startapp ser
setting注册
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'students.apps.StudentsConfig',
'ser.apps.SerConfig',
]
路由分发
from django.contrib import admin
from django.urls import path,include urlpatterns = [
path('admin/', admin.site.urls),
path('student/',include("students.urls")),
path('ser/',include("ser.urls")),
]
配置urls
from rest_framework.routers import DefaultRouter
from django.urls import path,re_path
from ser import views urlpatterns = [
path('student1/',views.Student1.as_view()),
re_path(r'student2/(?P<pk>\d+)/$',views.Student2.as_view()),
] # 路由列表
定义序列化类
1.2 创建Serializer对象
定义好Serializer类后,就可以创建Serializer对象了。
Serializer的构造方法为:
Serializer(instance=None, data=empty, **kwarg)
说明:
1)用于序列化时,将模型类对象传入instance参数
2)用于反序列化时,将要被反序列化的数据传入data参数
3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如
serializer = StudentSerializer(student, context={'request': request})
通过context参数附加的数据,可以通过Serializer对象的context属性获取。
声明:
使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。
序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。
序列化器的字段声明类似于我们前面使用过的表单系统。
开发restful api时,序列化器会帮我们把模型数据转换成字典.
drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典.
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/serializers.py
from rest_framework import serializers
# 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField()
# 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ]
# 3. 可选[ 用于对客户端提交的数据进行验证 ]
# 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库
视图文件
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/views.py
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list)
print(111,serializer.data)
return JsonResponse(serializer.data)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data)
1.3 序列化使用POSTMAN调试
打印返回数据
当获取所有数据时
多个参数需要添加many=True,表示本次序列化器转换如果有多个模型对象列参数,则必须声明 Many=True
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list,many=True)
print(111,serializer.data)
return JsonResponse(serializer.data)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data)
访问另一个错误
json返回,添加safe=False
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list,many=True)
print(111,serializer.data)
return JsonResponse(serializer.data,safe=False)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data)
POSTMAN调试
打印数据
111 [OrderedDict([('id', 1), ('name', '令狐冲'), ('sex', True), ('age', 18), ('class_null', '205'), ('description', 'hello mysqlf')]), OrderedDict([('id', 2), ('name', '任我行'), ('sex', True), ('age', 55), ('class_null', '203'), ('description', 'hello let me go')]), OrderedDict([('id', 3), ('name', '李寻欢'), ('sex', True), ('age', 33), ('class_null', '207'), ('description', 'be happy lee')]), OrderedDict([('id', 5), ('name', '李莫愁'), ('sex', True), ('age', 36), ('class_null', '208'), ('description', 'Don’t Worry Lee')])]
[20/Apr/2020 02:02:37] "GET /ser/student1/ HTTP/1.1" 200 479
反序列化
二 反序列化和数据校验
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
- 验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启。
- 验证成功,可以通过序列化器对象的validated_data属性获取数据。
在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。
ser应用下的serializers.py文件:
在drf中,对于客户端提供的数据,往往需要验证数据的有效性,这部分代码是写在序列化器中的。
在序列化器中,已经提供三个地方给我们针对客户端提交的数据进行验证。
1. 内置选项,字段声明的小圆括号中,以选项存在作为验证提交
2. 自定义方法,在序列化器中作为对象方法来提供验证[ 这部分验证的方法,必须以"validate_<字段>" 或者 "validate" 作为方法名 ]
3. 自定义函数,在序列化器外部,提前声明一个验证代码,然后在字段声明的小圆括号中,通过 "validators=[验证函数1,验证函数2...]"
2.1 内置选项校验
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/serializers.py
from rest_framework import serializers # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField()
# 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ]
# 3. 可选[ 用于对客户端提交的数据进行验证 ]
# 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ] class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4)
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0)
路由配置
from rest_framework.routers import DefaultRouter
from django.urls import path,re_path
from ser import views urlpatterns = [
path('student1/',views.Student1.as_view()),
re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()),
#数据校验
path('student2/',views.Student3.as_view()),
] # 路由列表
视图配置
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list,many=True)
print(111,serializer.data)
return JsonResponse(serializer.data,safe=False)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data) import json
from ser.serializers import Student2Serializer
class Student3(View):
def post(self,request):
#获取提交数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student2Serializer(data=data_dict)
#serializer.is_valid() #出现异常不会报错 serializer.is_valid(raise_exception=True)
print ("Errors",serializer.errors)
print (serializer.validated_data)
return JsonResponse(serializer.data)
做一个新增数据的操作
配置setting,取消crfs验证
#'django.middleware.csrf.CsrfViewMiddleware',
提交,查看响应
提交合法数据
结果
数据库并没有添加新的数据,是因为上面仅仅只是校验数据
2.2 自定义方法
验证单个字段是否合法,name不能是root
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/serializers.py
from rest_framework import serializers # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ] class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4)
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
添加一个root数据
结果
其他异常
from rest_framework import serializers # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ] class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4)
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age') if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。") return attrs
使用不合法数据访问
结果
2.3 自定义函数校验
from rest_framework import serializers # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ]
#自定义函数
def check_user(data):
if data == "darren":
raise serializers.ValidationError("用户名不能为darren!")
return data class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4,validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age') if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。") return attrs
不合法数据以及异常信息
结果
三 反序列化数据保存
可以通过在序列化器中实现create()和update()两个方法来实现。
3.1 create方法
serializer文件
from rest_framework import serializers
from students.models import Student # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ]
#自定义函数
def check_user(data):
if data == "darren":
raise serializers.ValidationError("用户名不能为darren!")
return data class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4,validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs
#create方法
def create(self, validated_data):
print(validated_data)
name = validated_data.get("name")
sex = validated_data.get("sex")
age = validated_data("age")
instance = Student.objects.create(name=name,sex=sex,age=age)
#instance = Student.objects.create(**validated_data)
return instance
views需要保存
import json
from ser.serializers import Student2Serializer
class Student3(View):
def post(self,request):
#获取提交数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student2Serializer(data=data_dict)
#serializer.is_valid() #出现异常不会报错
serializer.is_valid(raise_exception=True)
serializer.save()
print ("Errors",serializer.errors)
print (serializer.validated_data)
return JsonResponse(serializer.data)
post添加一个数据
查看数据库
已经创建新数据
3.2 upload更新数据
serializer文件
from rest_framework import serializers
from students.models import Student # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ]
#自定义函数
def check_user(data):
if data == "darren":
raise serializers.ValidationError("用户名不能为darren!")
return data class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4,validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs
def create(self, validated_data):
print(validated_data)
name = validated_data.get("name")
sex = validated_data.get("sex")
age = validated_data.get("age")
instance = Student.objects.create(name=name,sex=sex,age=age)
#instance = Student.objects.create(**validated_data)
return instance
#更新数据
def update(self, instance, validated_data):
#用于在反序列化中对于验证完成的数据进行保存更新
instance.name = validated_data.get("name")
instance.age = validated_data.get("age")
instance.sex = validated_data.get("sex")
instance.save()
return instance
配置路由
from rest_framework.routers import DefaultRouter
from django.urls import path,re_path
from ser import views urlpatterns = [
path('student1/',views.Student1.as_view()),
re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()),
#数据校验
path('student2/',views.Student3.as_view()),
#修改更新数据
re_path(r'^student2/(?P<pk>\d+)/$',views.Student4.as_view()),
] # 路由列表
视图文件配置
如果创建序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,则调用save()方法的时候,update()被调用。
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list,many=True)
print(111,serializer.data)
return JsonResponse(serializer.data,safe=False)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data) import json
from ser.serializers import Student2Serializer
class Student3(View):
def post(self,request):
#获取提交数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student2Serializer(data=data_dict)
#serializer.is_valid() #出现异常不会报错
serializer.is_valid(raise_exception=True)
serializer.save()
print ("Errors",serializer.errors)
print (serializer.validated_data)
return JsonResponse(serializer.data) class Student4(View):
def put(self,request,pk):
# 反序列化用户提交的数据
data = request.body.decode()
data_dict = json.loads(data)
student_obj = Student.objects.get(pk=pk)
# 调用序列化器进行实例化
# 有instance参数,调用save方法,就会调用update方法。
serializer = Student2Serializer(instance=student_obj,data=data_dict)
# is_valid在执行的时候,会自动先后调用 字段的内置选项,自定义验证方法,自定义验证函数
# 调用序列化器中写好的验证代码
# raise_exception=True 抛出验证错误信息,并阻止代码继续往后运行
# 验证结果
serializer.is_valid(raise_exception=True)
# save 表示让序列化器开始执行反序列化代码。create和update的代码
serializer.save()
return JsonResponse(serializer.validated_data)
PUT修改数据
提交查看数据
四 序列化与反序列化合并使用
ser序列化配置
from rest_framework import serializers
from students.models import Student # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ]
#自定义函数
def check_user(data):
if data == "darren":
raise serializers.ValidationError("用户名不能为darren!")
return data class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4,validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs
def create(self, validated_data):
print(validated_data)
name = validated_data.get("name")
sex = validated_data.get("sex")
age = validated_data.get("age")
instance = Student.objects.create(name=name,sex=sex,age=age)
#instance = Student.objects.create(**validated_data)
return instance
#更新数据
def update(self, instance, validated_data):
#用于在反序列化中对于验证完成的数据进行保存更新
instance.name = validated_data.get("name")
instance.age = validated_data.get("age")
instance.sex = validated_data.get("sex")
instance.save()
return instance class Student3Serializer(serializers.Serializer):
# 字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4, validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0)
# model
#3.数据校验,验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs def create(self, validated_data):
print(validated_data)
name = validated_data.get("name")
sex = validated_data.get("sex")
age = validated_data.get("age")
instance = Student.objects.create(name=name,sex=sex,age=age)
#instance = Student.objects.create(**validated_data)
return instance def update(self, instance, validated_data):
#用于在反序列化中对于验证完成的数据进行保存更新
instance.name = validated_data.get("name")
instance.age = validated_data.get("age")
instance.sex = validated_data.get("sex")
instance.save()
return instance
路由配置
from rest_framework.routers import DefaultRouter
from django.urls import path,re_path
from ser import views urlpatterns = [
path('student1/',views.Student1.as_view()),
re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()),
#数据校验
path('student2/',views.Student3.as_view()),
#修改更新数据
re_path(r'^student2/(?P<pk>\d+)/$',views.Student4.as_view()), #序列化整合使用
path('student3/',views.Student5.as_view()),
#修改更新数据
re_path(r'^student3/(?P<pk>\d+)/$',views.Student6.as_view()), ] # 路由列表
视图配置
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse,HttpResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list,many=True)
print(111,serializer.data)
return JsonResponse(serializer.data,safe=False)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data) import json
from ser.serializers import Student2Serializer
class Student3(View):
def post(self,request):
#获取提交数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student2Serializer(data=data_dict)
#serializer.is_valid() #出现异常不会报错
serializer.is_valid(raise_exception=True)
serializer.save()
print ("Errors",serializer.errors)
print (serializer.validated_data)
return JsonResponse(serializer.data) class Student4(View):
def put(self,request,pk):
# 反序列化用户提交的数据
data = request.body.decode()
data_dict = json.loads(data)
student_obj = Student.objects.get(pk=pk)
# 调用序列化器进行实例化
# 有instance参数,调用save方法,就会调用update方法。
serializer = Student2Serializer(instance=student_obj,data=data_dict)
# is_valid在执行的时候,会自动先后调用 字段的内置选项,自定义验证方法,自定义验证函数
# 调用序列化器中写好的验证代码
# raise_exception=True 抛出验证错误信息,并阻止代码继续往后运行
# 验证结果
serializer.is_valid(raise_exception=True)
# save 表示让序列化器开始执行反序列化代码。create和update的代码
serializer.save()
return JsonResponse(serializer.validated_data) from ser.serializers import Student3Serializer
class Student5(View):
def get(self,request):
#获取所有数据
student_list = Student.objects.all()
serializer = Student3Serializer(instance=student_list,many=True)
return JsonResponse(serializer.data,safe=False)
def post(self,request):
#新增一条数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student3Serializer(data=data_dict)
#数据检验
serializer.is_valid(raise_exception=True)
#数据保存
serializer.save()
return JsonResponse(serializer.data) class Student6(View):
def get(self, request, pk):
#获取一条
student_obj = Student.objects.get(pk=pk)
serializer = Student3Serializer(instance=student_obj)
return JsonResponse(serializer.data) def put(self, request, pk):
# 更新一条数据
data = request.body.decode()
data_dict = json.loads(data)
student_obj = Student.objects.get(pk=pk)
serializer = Student3Serializer(instance=student_obj,data=data_dict)
serializer.is_valid(raise_exception=True)
serializer.save()
return JsonResponse(serializer.data)
def delete(self,request,pk):
student_obj = Student.objects.get(pk=pk)
student_obj.delete()
return HttpResponse("Delete Success")
POSTMAN调试
获取所有
添加一条数据
数据库查看
修改一条数据
查看数据库
删除
结果
查看数据库
五 模型类序列化器
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
在ser应用下serializers.py文件定义模型类序列化器:
这种基于ModelSerializer声明序列化器的方式有三个优势:
1. 可以直接通过声明当前序列化器中指定的模型中把字段声明引用过来
2. ModelSerializer是继承了Serializer的所有功能和方法,同时还编写update和create
3. 模型中同一个字段中关于验证的选项,也会被引用到序列化器中一并作为选项参与验证
from rest_framework import serializers
from students.models import Student # 所有的自定义序列化器必须直接或间接继承于 serializers.Serializer
class StudentSerializer(serializers.Serializer):
# 声明序列化器
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
id = serializers.IntegerField()
name = serializers.CharField()
sex = serializers.BooleanField()
age = serializers.IntegerField()
class_null = serializers.CharField()
description = serializers.CharField() # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ] # 4. 可选[ 用于把通过验证的数据进行数据库操作,保存到数据库 ]
#自定义函数
def check_user(data):
if data == "darren":
raise serializers.ValidationError("用户名不能为darren!")
return data class Student2Serializer(serializers.Serializer):
#字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4,validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可选[ 如果序列化器继承的是ModelSerializer,则需要声明对应的模型和字段, ModelSerializer是Serializer的子类 ] # 3. 可选[ 用于对客户端提交的数据进行验证 ]
#验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs
def create(self, validated_data):
print(validated_data)
name = validated_data.get("name")
sex = validated_data.get("sex")
age = validated_data.get("age")
instance = Student.objects.create(name=name,sex=sex,age=age)
#instance = Student.objects.create(**validated_data)
return instance
#更新数据
def update(self, instance, validated_data):
#用于在反序列化中对于验证完成的数据进行保存更新
instance.name = validated_data.get("name")
instance.age = validated_data.get("age")
instance.sex = validated_data.get("sex")
instance.save()
return instance class Student3Serializer(serializers.Serializer):
# 字段声明
# 1. 字段声明[ 要转换的字段,当然,如果写了第二部分代码,有时候也可以不用写字段声明 ]
name = serializers.CharField(max_length=10, min_length=4, validators=[check_user])
sex = serializers.BooleanField(required=True)
age = serializers.IntegerField(max_value=150, min_value=0)
# model
#3.数据校验,验证单个字段值的合法性
def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data
def validate_age(self, data):
if data < 18:
raise serializers.ValidationError("年龄不能小于18")
return data #验证多个字段值的合法性
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs def create(self, validated_data):
print(validated_data)
name = validated_data.get("name")
sex = validated_data.get("sex")
age = validated_data.get("age")
instance = Student.objects.create(name=name,sex=sex,age=age)
#instance = Student.objects.create(**validated_data)
return instance def update(self, instance, validated_data):
#用于在反序列化中对于验证完成的数据进行保存更新
instance.name = validated_data.get("name")
instance.age = validated_data.get("age")
instance.sex = validated_data.get("sex")
instance.save()
return instance #使用model模型类序列化
class Student4ModelSerializer(serializers.ModelSerializer):
class Meta:
model = Student
# fields = "__all__" # 表示引用所有字段
fields = ["id", "name", "age", "class_null", "is_18"] # is_18 为自定制字段,需要在models里自定义方法。
# exclude = ["age"] # 使用exclude可以明确排除掉哪些字段, 注意不能和fields同时使用。
# 传递额外的参数,为ModelSerializer添加或修改原有的选项参数
extra_kwargs = {
"name": {"max_length": 10, "min_length": 4, "validators": [check_user]},
"age": {"max_value": 150, "min_value": 0},
} def validate_name(self, data):
if data == "root":
raise serializers.ValidationError("用户名不能为root!")
return data def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if name == "renwoxing" and age == 22:
raise serializers.ValidationError("任我行已经50多了。。。")
return attrs
#数据保存,不用自己写方法,在model已经写好了creat和update
urls
from rest_framework.routers import DefaultRouter
from django.urls import path,re_path
from ser import views urlpatterns = [
path('student1/',views.Student1.as_view()),
re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()),
#数据校验
path('student2/',views.Student3.as_view()),
#修改更新数据
re_path(r'^student2/(?P<pk>\d+)/$',views.Student4.as_view()), #序列化整合使用
path('student3/',views.Student5.as_view()),
re_path(r'^student3/(?P<pk>\d+)/$',views.Student6.as_view()),
#模型类序列化整合使用
path('student4/',views.Student7.as_view()),
re_path(r'^student4/(?P<pk>\d+)/$',views.Student8.as_view()),
] # 路由列表
views视图
from django.shortcuts import render
from django.views import View
from students.models import Student
from ser.serializers import StudentSerializer
from django.http import JsonResponse,HttpResponse
# Create your views here.
class Student1(View):
def get(self,request):
"""使用序列化器进行数据的序列化操作,序列化器转换一条数据[模型转换成字典]"""
#获取所有数据,接收客户端传过来的参数,进行过滤查询,先查出学生对象
student_list = Student.objects.all()
#序列化操作
serializer = StudentSerializer(instance=student_list,many=True)
print(111,serializer.data)
return JsonResponse(serializer.data,safe=False)
class Student2(View):
def get(self,request,pk):
student_obj = Student.objects.get(pk=pk)
#序列化操作,StudentSerializer(instance=模型对象或者模型列表,客户端提交的数据,额外要传递到序列化器中使用的数据)
serializer = StudentSerializer(instance=student_obj)
print(serializer.data)
return JsonResponse(serializer.data) import json
from ser.serializers import Student2Serializer
class Student3(View):
def post(self,request):
#获取提交数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student2Serializer(data=data_dict)
#serializer.is_valid() #出现异常不会报错
serializer.is_valid(raise_exception=True)
serializer.save()
print ("Errors",serializer.errors)
print (serializer.validated_data)
return JsonResponse(serializer.data) class Student4(View):
def put(self,request,pk):
# 反序列化用户提交的数据
data = request.body.decode()
data_dict = json.loads(data)
student_obj = Student.objects.get(pk=pk)
# 调用序列化器进行实例化
# 有instance参数,调用save方法,就会调用update方法。
serializer = Student2Serializer(instance=student_obj,data=data_dict)
# is_valid在执行的时候,会自动先后调用 字段的内置选项,自定义验证方法,自定义验证函数
# 调用序列化器中写好的验证代码
# raise_exception=True 抛出验证错误信息,并阻止代码继续往后运行
# 验证结果
serializer.is_valid(raise_exception=True)
# save 表示让序列化器开始执行反序列化代码。create和update的代码
serializer.save()
return JsonResponse(serializer.validated_data) from ser.serializers import Student3Serializer
class Student5(View):
def get(self,request):
#获取所有数据
student_list = Student.objects.all()
serializer = Student3Serializer(instance=student_list,many=True)
return JsonResponse(serializer.data,safe=False)
def post(self,request):
#新增一条数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student3Serializer(data=data_dict)
#数据检验
serializer.is_valid(raise_exception=True)
#数据保存
serializer.save()
return JsonResponse(serializer.data) class Student6(View):
def get(self, request, pk):
#获取一条
student_obj = Student.objects.get(pk=pk)
serializer = Student3Serializer(instance=student_obj)
return JsonResponse(serializer.data) def put(self, request, pk):
# 更新一条数据
data = request.body.decode()
data_dict = json.loads(data)
student_obj = Student.objects.get(pk=pk)
serializer = Student3Serializer(instance=student_obj,data=data_dict)
serializer.is_valid(raise_exception=True)
serializer.save()
return JsonResponse(serializer.data)
def delete(self,request,pk):
student_obj = Student.objects.get(pk=pk)
student_obj.delete()
return HttpResponse("Delete Success") from ser.serializers import Student4Serializer
class Student7(View):
def get(self, request):
# 获取所有数据
student_list = Student.objects.all()
serializer = Student4Serializer(instance=student_list, many=True)
return JsonResponse(serializer.data, safe=False) def post(self, request):
# 新增一条数据
data = request.body.decode()
data_dict = json.loads(data)
serializer = Student4Serializer(data=data_dict)
# 数据检验
serializer.is_valid(raise_exception=True)
# 数据保存
serializer.save()
return JsonResponse(serializer.data)
class Student8(View):
def get(self, request, pk):
#获取一条
student_obj = Student.objects.get(pk=pk)
serializer = Student4Serializer(instance=student_obj)
return JsonResponse(serializer.data) def put(self, request, pk):
# 更新一条数据
data = request.body.decode()
data_dict = json.loads(data)
student_obj = Student.objects.get(pk=pk)
serializer = Student4Serializer(instance=student_obj,data=data_dict)
serializer.is_valid(raise_exception=True)
serializer.save()
return JsonResponse(serializer.data)
def delete(self,request,pk):
student_obj = Student.objects.get(pk=pk)
student_obj.delete()
return HttpResponse("Delete Success")
使用POSTMAN进行调试,效果一样
参考:
https://www.cnblogs.com/Michael--chen/p/11222143.html
老男孩教育:https://www.oldboyedu.com/
066.Python框架DRF之序列化器Serializer的更多相关文章
- 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用
写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...
- 一: DRF web应用框架基础,及序列化器的使用
---恢复内容开始--- 一: web 应用模式(有两种) 1: 前后端不分离(前端从后端直接获取数据) 2: 前后端分离 二: api 接口 原因一: 为了在团队内部形成共识.防止个人习惯差异引起的 ...
- drf之序列化器的使用
一.序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经 ...
- Cf序列化器-Serializer解析
Cf序列化器-Serializer 定义序列化器 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Seri ...
- day82 序列化器-Serializer
目录 一.序列化器的基本功能 二.定义序列化器 三.创建Serializers对象 四.序列化器的使用 1 序列化 2 反序列化 2.1 数据验证(类比forms组件) 2.2 数据保存 一.序列化器 ...
- DRF 序列化器-Serializer (2)
作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...
- DRF框架之ModelSerializer序列化器
ModelSerializer是Serializer的子类,序列化和反序列化跟Serializer一样. ModelSerializer与常规的Serializer相同,但提供了: 基于模型类自动生成 ...
- DRF中序列化器定义及使用
首先需要明白序列化和反序列化的定义及作用: 序列化是将程序语言转换为JSON/XML; 反序列化是将JSON/XML转换为程序语言; 对应到Django中,序列化即把模型对象转换为字典形式, 在返回给 ...
- drf的序列化器
三流 import sys #标准输出流 sys.stdout.write('123\n') sys.stdout.write('456\n') #标准输入流 res=sys.stdin.readli ...
随机推荐
- java面试-JVM调优和参数配置,如何查看JVM系统参数默认值
一.JVM的参数类型: 1.标配参数: java -version java -help 2.X参数: -Xmixed 混合模式(先编译后执行) -Xint 解释执行 -Xcomp 第一次使用就编译 ...
- 1. HTML <fieldset> 标签
定义和用法 fieldset 元素可将表单内的相关元素分组. <fieldset> 标签将表单内容的一部分打包,生成一组相关表单的字段. 当一组表单元素放到 <fieldset> ...
- 什么?女神发了朋友圈,快来围观之Java设计模式:观察者模式
目录 观察者模式 示例 定义 设计原则 意图 主要解决问题 何时使用 优缺点 女神和追求者的故事 Java中的实现 观察者模式 示例 微信公众号,关注就可以收到推送的消息,取消关注就不会收到 定义 定 ...
- Day07_33_链表
链表 单链表 双向链表 * 什么是双向链表? 双向链表是链表的一种,由节点组成,每个数据结点中都有两个指针,分别指向直接后继和直接前驱. ![](https://img2020.cnblogs.com ...
- 浅谈 C# Assembly 与 IL (一):C# Assembly 与 Reflection
作者:Compasslg 前言 前一阵子想利用闲余时间写一个 Unity 游戏的翻译工具,主要是用于翻译一些内嵌在代码中的文本,最初想偷懒看了一下网上的教学推荐说可以先利用DnSpy.ILSpy等工具 ...
- 使用Font Awesome替换EasyUI的图标
用过EasyUI的朋友都知道,大部分组件都有一个iconCls属性,用于显示一个图标.但是EasyUI自带图标数量少.不美观,于是想到了使用Font Awesome来更换和拓展这些图标. 先看看Eas ...
- 痞子衡嵌入式:利用i.MXRT1xxx系列内部DCP引擎计算Hash值时需特别处理L1 D-Cache
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是利用i.MXRT1xxx系列内部DCP引擎计算Hash值时需特别处理L1 D-Cache. 关于i.MXRT1xxx系列内部通用数据协处 ...
- 脚本加载后执行JS回调函数的方法
动态脚本简单示例 // IE下: var HEAD = document.getElementsByTagName('head')[0] || document.documentElement var ...
- 【ORM】Mybatis与JPA的区别
Mybatis与JPA的区别: 1.ORM映射不同: Mybatis是半自动的ORM框架,提供数据库与结果集的映射: JPA(Hibernate)是全自动的ORM框架,提供对象与数据库的映射: 2.可 ...
- KMP中next数组的理解
next数组是KMP的核心,但对于next数组我们总是有时候感觉明白了,但有时候又感觉没明白,现在我就说下我自己对KMP中next数组的理解,首先next[i]上的数字的意义,next[i]表示的是当 ...