zoukankan      html  css  js  c++  java
  • Django Rest Framework组件:序列化与反序列化模块Serializer

    作者:梦中泪

    一 序列化器-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<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/

     
  • 相关阅读:
    二叉搜索树
    【树】List Leaves
    模板——dijkstra单源最短路
    余数求和——除法分块
    倍增——ST表
    线段树——内存池
    线段树——模板
    洛谷 P1498 南蛮图腾
    洛谷 P2199 最后的迷宫
    洛谷 P1495 中国剩余定理
  • 原文地址:https://www.cnblogs.com/-wenli/p/13235613.html
Copyright © 2011-2022 走看看