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 ...
随机推荐
- vue+quasar+electron+springboot+mysql撸一个TODO LIST 看板
先看效果 写本项目的目的有几点: 学习下vue+electron桌面开发 学习下java和spring开发(本人一直使用PHP) 一直缺少一款能适合自己的TODO LIST软件,能有桌面端的 可直接打 ...
- docker之镜像配置
以管理员sudo执行以下命令 docker ps -a 查看镜像的id docker exec -it 镜像id /bin/bash -i表示交互模式 -t表示启动容器进入命令行 加入这两参数,容器创 ...
- 几十行代码实现ASP.NET Core自动依赖注入
在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...
- (Set, Map, Collections工具类)JAVA集合框架二
Java集合框架部分细节总结二 Set 实现类:HashSet,TreeSet HashSet 基于HashCode计算元素存放位置,当计算得出哈希码相同时,会调用equals判断是否相同,相同则拒绝 ...
- buuctf pwn wp---part1
pwn难啊 1.test_your_nc 测试你nc,不用说,连上就有. 2.rip ida中已经包含了system函数: 溢出,覆盖rip为fun函数,peda计算偏移为23: from pwn i ...
- 4-1 Postman脚本的应用
前面我们讲解了在接口发送每个请求,得到响应.这是接口本身的问题.但是"请求前后"的动作,是怎么处理的?比如在发送一个请求前,需要获取当前的时间戳,或者对我们的变量进行参数化,设置变 ...
- SQL 查询的执行顺序
SELECT语句的完整语法如下 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN & ...
- 【swagger】 swagger-ui的升级版swagger-bootstrap-ui
swagger-bootstrap-ui是基于swagger-ui做了一些优化拓展: swagger-ui的界面: swagger-bootstrap-ui界面: 相比于原生的swagger-ui , ...
- hdu3117 斐波那契前后4位
题意: 求斐波那契的前后4位,n <= 10^8. 思路: 至于前四位,和hdu1568的求法一样: http://blog.csdn.net/u013761 ...
- hdu4642博弈(矩阵)
题意: 给一个01矩阵,每次可以选择1的格子,选择之后以他为左上角的矩阵全都取反,两个人轮班取,不能取的人输. 思路: 博弈的题目,结论是右下角是0就输,1就赢,原因可以这么 ...