python

Django Rest Framework组件:序列化与反序列化模块Serializer - -零 - 博客园

文章暂存

systemime
2021-06-03
47 min

摘要.

# 一 序列化器 - Serializer

  1. 序列化:查询时,序列化器会把模型对象转换成字典, 然后转换为 json 字符串,返回 json 字符串。
  2. 反序列化:接收客户端的 json 数据, 然后转为字典, 序列化器可以把字典转成模型,再完成数据校验功能与数据保存功能。

# 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\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\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\d+)/,views.Student2.asview()),#数据校验path(student2/,views.Student3.asview()),#修改更新数据repath(rstudent2/(?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\d+)/,views.Student2.asview()),#数据校验path(student2/,views.Student3.asview()),#修改更新数据repath(rstudent2/(?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\d+)/,views.Student2.asview()),#数据校验path(student2/,views.Student3.asview()),#修改更新数据repath(rstudent2/(?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/ https://www.cnblogs.com/-wenli/p/13235613.html

上次编辑于: 6/5/2021, 11:41:57 AM