一 序列化器-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属性获取。

  声明:

  1. 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。

  2. 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。

  3. 序列化器的字段声明类似于我们前面使用过的表单系统。

  4. 开发restful api时,序列化器会帮我们把模型数据转换成字典.

  5. 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的更多相关文章

  1. 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用

    写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...

  2. 一: DRF web应用框架基础,及序列化器的使用

    ---恢复内容开始--- 一: web 应用模式(有两种) 1: 前后端不分离(前端从后端直接获取数据) 2: 前后端分离 二: api 接口 原因一: 为了在团队内部形成共识.防止个人习惯差异引起的 ...

  3. drf之序列化器的使用

    一.序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经 ...

  4. Cf序列化器-Serializer解析

    Cf序列化器-Serializer 定义序列化器 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Seri ...

  5. day82 序列化器-Serializer

    目录 一.序列化器的基本功能 二.定义序列化器 三.创建Serializers对象 四.序列化器的使用 1 序列化 2 反序列化 2.1 数据验证(类比forms组件) 2.2 数据保存 一.序列化器 ...

  6. DRF 序列化器-Serializer (2)

    作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...

  7. DRF框架之ModelSerializer序列化器

    ModelSerializer是Serializer的子类,序列化和反序列化跟Serializer一样. ModelSerializer与常规的Serializer相同,但提供了: 基于模型类自动生成 ...

  8. DRF中序列化器定义及使用

    首先需要明白序列化和反序列化的定义及作用: 序列化是将程序语言转换为JSON/XML; 反序列化是将JSON/XML转换为程序语言; 对应到Django中,序列化即把模型对象转换为字典形式, 在返回给 ...

  9. drf的序列化器

    三流 import sys #标准输出流 sys.stdout.write('123\n') sys.stdout.write('456\n') #标准输入流 res=sys.stdin.readli ...

随机推荐

  1. CODING 首届金融科技技术交流闭门会议顺利召开

    近期,由腾讯云旗下一站式 DevOps 开发平台 CODING 和中国 DevOps 社区主办的深圳第十一届 Meetup 圆满结束,会上三位专家分享了自己独到的行业见解,腾讯云 CODING Dev ...

  2. Go语言操作数据库及其常规操作

    Go操作MySQL 安装: go get -u github.com/go-sql-driver/mysql GO语言的操作数据库的驱动原生支持连接池, 并且是并发安全的 标准库没有具体的实现 只是列 ...

  3. 关于Maven中<packaging>产生的一些问题

    关于Maven中产生的一些问题 一.项目的打包类型 jar 默认的打包格式 war 打包成需要部署的项目 pom 父类型为pom类型 二. pom 简单来说,一个多模块项目通过一个父POM 引用一个或 ...

  4. 一.文件处理和json模块(容易混淆知识点即用法)

    一.文件处理 注意点1: 打开文件包含两部分资源:操作系统级打开得文件+应用程序的变量. 在操作完毕一个文件时,必须把该文件的两部分资源一个不落的回收 如下: f.close() #回收操作系统级打开 ...

  5. 华为AppTouch创新订阅模式,出海创收事半功倍

    去年是中国游戏在全球舞台大放异彩的一年:在国内游戏市场竞争愈发激烈的情况下,不少厂商将目光投向更为广阔的海外市场,把海外视为新的增长点.<PUBG Mobile><万国觉醒>等 ...

  6. js的13种继承

    js继承的13种方式 也可以说只有12种,ES6的extend 也是12种方法之一-寄生继承的语法糖 1.原型链法 代码示例 Child.prototype = new Parent(); 所属模式: ...

  7. 使用numba加速python科学计算

    技术背景 python作为一门编程语言,有非常大的生态优势,但是其执行效率一直被人诟病.纯粹的python代码跑起来速度会非常的缓慢,因此很多对性能要求比较高的python库,需要用C++或者Fort ...

  8. CSS快速入门基础篇,让你快速上手(附带代码案例)

    1.什么是CSS 学习思路 CSS是什么 怎么去用CSS(快速上手) CSS选择器(难点也是重点) 网页美化(文字,阴影,超链接,列表,渐变等) 盒子模型 浮动 定位 网页动画(特效效果) 项目格式: ...

  9. 一文带你掌握MySQL查询优化技能

    查询优化本就不是一蹴而就的,需要学会使用对应的工具.借鉴别人的经验来对SQL进行优化,并且提升自己. 分享一套博主觉得讲的很详细很实用的MySQL教程给大家,可直接点击观看! https://www. ...

  10. Linux下查看CPU、内存占用率

    linux下查看最消耗CPU.内存的进程 CPU占用最多的前10个进程: ps auxw|head -1;ps auxw|sort -rn -k3|head -10 内存消耗最多的前10个进程: ps ...