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/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM