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(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。
- 验证成功,可以通过序列化器对象的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进行调试,效果一样
参考:
---------------------------------------------------------------------------
个性签名:我以为我很颓废,今天我才知道,原来我早报废了。
如果觉得本篇文章最您有帮助,欢迎转载,且在文章页面明显位置给出原文链接!记得在右下角点个“推荐”,博主在此感谢!