一 序列化器-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(instance=None, data=empty, **kwarg)
說明:
1)用於序列化時,將模型類對象傳入instance參數
2)用於反序列化時,將要被反序列化的數據傳入data參數
3)除了instance和data參數外,在構造Serializer對象時,還可通過context參數額外添加數據,如
serializer = StudentSerializer(student, context={'request': request})
通過context參數附加的數據,可以通過Serializer對象的context屬性獲取。
聲明:
-
-
序列化器無法直接接收數據,需要我們在視圖中創建序列化器對象時把使用的數據傳遞過來。
-
序列化器的字段聲明類似於我們前面使用過的表單系統。
-
開發restful api時,序列化器會幫我們把模型數據轉換成字典.
-
drf提供的視圖會幫我們把字典轉換成json,或者把客戶端發送過來的數據轉換字典.
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/serializers.py
from rest_framework import serializers # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫
視圖文件
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/views.py
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list)
print(111,serializer.data)
return JsonResponse(serializer.data) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data)
1.3 序列化使用POSTMAN調試
打印返回數據
當獲取所有數據時
多個參數需要添加many=True,表示本次序列化器轉換如果有多個模型對象列參數,則必須聲明 Many=True
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list,many=True) print(111,serializer.data) return JsonResponse(serializer.data) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data)
訪問另一個錯誤
json返回,添加safe=False
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list,many=True) print(111,serializer.data) return JsonResponse(serializer.data,safe=False) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data)
POSTMAN調試
打印數據
111 [OrderedDict([('id', 1), ('name', '令狐沖'), ('sex', True), ('age', 18), ('class_null', '205'), ('description', 'hello mysqlf')]), OrderedDict([('id', 2), ('name', '任我行'), ('sex', True), ('age', 55), ('class_null', '203'), ('description', 'hello let me go')]), OrderedDict([('id', 3), ('name', '李尋歡'), ('sex', True), ('age', 33), ('class_null', '207'), ('description', 'be happy lee')]), OrderedDict([('id', 5), ('name', '李莫愁'), ('sex', True), ('age', 36), ('class_null', '208'), ('description', 'Don’t Worry Lee')])] [20/Apr/2020 02:02:37] "GET /ser/student1/ HTTP/1.1" 200 479
反序列化
二 反序列化和數據校驗
使用序列化器進行反序列化時,需要對數據進行驗證后,才能獲取驗證成功的數據或保存成模型類對象。
在獲取反序列化的數據前,必須調用is_valid()方法進行驗證,驗證成功返回True,否則返回False。
- 驗證成功,可以通過序列化器對象的validated_data屬性獲取數據。
在定義序列化器時,指明每個字段的序列化類型和選項參數,本身就是一種驗證行為。
ser應用下的serializers.py文件:
在drf中,對於客戶端提供的數據,往往需要驗證數據的有效性,這部分代碼是寫在序列化器中的。 在序列化器中,已經提供三個地方給我們針對客戶端提交的數據進行驗證。 1. 內置選項,字段聲明的小圓括號中,以選項存在作為驗證提交 2. 自定義方法,在序列化器中作為對象方法來提供驗證[ 這部分驗證的方法,必須以"validate_<字段>" 或者 "validate" 作為方法名 ] 3. 自定義函數,在序列化器外部,提前聲明一個驗證代碼,然后在字段聲明的小圓括號中,通過 "validators=[驗證函數1,驗證函數2...]"
2.1 內置選項校驗
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/serializers.py
from rest_framework import serializers # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0)
路由配置
from rest_framework.routers import DefaultRouter from django.urls import path,re_path from ser import views urlpatterns = [ path('student1/',views.Student1.as_view()), re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()), #數據校驗 path('student2/',views.Student3.as_view()), ] # 路由列表
視圖配置
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list,many=True) print(111,serializer.data) return JsonResponse(serializer.data,safe=False) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data) import json from ser.serializers import Student2Serializer class Student3(View): def post(self,request): #獲取提交數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student2Serializer(data=data_dict) #serializer.is_valid() #出現異常不會報錯 serializer.is_valid(raise_exception=True) print ("Errors",serializer.errors) print (serializer.validated_data) return JsonResponse(serializer.data)
做一個新增數據的操作
配置setting,取消crfs驗證
#'django.middleware.csrf.CsrfViewMiddleware',
提交,查看響應
提交合法數據
結果
數據庫並沒有添加新的數據,是因為上面僅僅只是校驗數據
2.2 自定義方法
驗證單個字段是否合法,name不能是root
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim ser/serializers.py
from rest_framework import serializers # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data
添加一個root數據
結果
其他異常
from rest_framework import serializers # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs
使用不合法數據訪問
結果
2.3 自定義函數校驗
from rest_framework import serializers # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] #自定義函數 def check_user(data): if data == "darren": raise serializers.ValidationError("用戶名不能為darren!") return data class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4,validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs
不合法數據以及異常信息
結果
三 反序列化數據保存
可以通過在序列化器中實現create()和update()兩個方法來實現。
3.1 create方法
serializer文件
from rest_framework import serializers from students.models import Student # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] #自定義函數 def check_user(data): if data == "darren": raise serializers.ValidationError("用戶名不能為darren!") return data class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4,validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs
#create方法 def create(self, validated_data): print(validated_data) name = validated_data.get("name") sex = validated_data.get("sex") age = validated_data("age") instance = Student.objects.create(name=name,sex=sex,age=age) #instance = Student.objects.create(**validated_data) return instance
views需要保存
import json from ser.serializers import Student2Serializer class Student3(View): def post(self,request): #獲取提交數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student2Serializer(data=data_dict) #serializer.is_valid() #出現異常不會報錯 serializer.is_valid(raise_exception=True) serializer.save() print ("Errors",serializer.errors) print (serializer.validated_data) return JsonResponse(serializer.data)
post添加一個數據
查看數據庫
已經創建新數據
3.2 upload更新數據
serializer文件
from rest_framework import serializers from students.models import Student # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] #自定義函數 def check_user(data): if data == "darren": raise serializers.ValidationError("用戶名不能為darren!") return data class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4,validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs def create(self, validated_data): print(validated_data) name = validated_data.get("name") sex = validated_data.get("sex") age = validated_data.get("age") instance = Student.objects.create(name=name,sex=sex,age=age) #instance = Student.objects.create(**validated_data) return instance #更新數據 def update(self, instance, validated_data): #用於在反序列化中對於驗證完成的數據進行保存更新 instance.name = validated_data.get("name") instance.age = validated_data.get("age") instance.sex = validated_data.get("sex") instance.save() return instance
配置路由
from rest_framework.routers import DefaultRouter from django.urls import path,re_path from ser import views urlpatterns = [ path('student1/',views.Student1.as_view()), re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()), #數據校驗 path('student2/',views.Student3.as_view()), #修改更新數據 re_path(r'^student2/(?P<pk>\d+)/$',views.Student4.as_view()), ] # 路由列表
視圖文件配置
如果創建序列化器對象的時候,沒有傳遞instance實例,則調用save()方法的時候,create()被調用,相反,如果傳遞了instance實例,則調用save()方法的時候,update()被調用。
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list,many=True) print(111,serializer.data) return JsonResponse(serializer.data,safe=False) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data) import json from ser.serializers import Student2Serializer class Student3(View): def post(self,request): #獲取提交數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student2Serializer(data=data_dict) #serializer.is_valid() #出現異常不會報錯 serializer.is_valid(raise_exception=True) serializer.save() print ("Errors",serializer.errors) print (serializer.validated_data) return JsonResponse(serializer.data) class Student4(View): def put(self,request,pk): # 反序列化用戶提交的數據 data = request.body.decode() data_dict = json.loads(data) student_obj = Student.objects.get(pk=pk) # 調用序列化器進行實例化 # 有instance參數,調用save方法,就會調用update方法。 serializer = Student2Serializer(instance=student_obj,data=data_dict) # is_valid在執行的時候,會自動先后調用 字段的內置選項,自定義驗證方法,自定義驗證函數 # 調用序列化器中寫好的驗證代碼 # raise_exception=True 拋出驗證錯誤信息,並阻止代碼繼續往后運行 # 驗證結果 serializer.is_valid(raise_exception=True) # save 表示讓序列化器開始執行反序列化代碼。create和update的代碼 serializer.save() return JsonResponse(serializer.validated_data)
PUT修改數據
提交查看數據
四 序列化與反序列化合並使用
ser序列化配置
from rest_framework import serializers from students.models import Student # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] #自定義函數 def check_user(data): if data == "darren": raise serializers.ValidationError("用戶名不能為darren!") return data class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4,validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs def create(self, validated_data): print(validated_data) name = validated_data.get("name") sex = validated_data.get("sex") age = validated_data.get("age") instance = Student.objects.create(name=name,sex=sex,age=age) #instance = Student.objects.create(**validated_data) return instance #更新數據 def update(self, instance, validated_data): #用於在反序列化中對於驗證完成的數據進行保存更新 instance.name = validated_data.get("name") instance.age = validated_data.get("age") instance.sex = validated_data.get("sex") instance.save() return instance class Student3Serializer(serializers.Serializer): # 字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4, validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # model #3.數據校驗,驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs def create(self, validated_data): print(validated_data) name = validated_data.get("name") sex = validated_data.get("sex") age = validated_data.get("age") instance = Student.objects.create(name=name,sex=sex,age=age) #instance = Student.objects.create(**validated_data) return instance def update(self, instance, validated_data): #用於在反序列化中對於驗證完成的數據進行保存更新 instance.name = validated_data.get("name") instance.age = validated_data.get("age") instance.sex = validated_data.get("sex") instance.save() return instance
路由配置
from rest_framework.routers import DefaultRouter from django.urls import path,re_path from ser import views urlpatterns = [ path('student1/',views.Student1.as_view()), re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()), #數據校驗 path('student2/',views.Student3.as_view()), #修改更新數據 re_path(r'^student2/(?P<pk>\d+)/$',views.Student4.as_view()), #序列化整合使用 path('student3/',views.Student5.as_view()), #修改更新數據 re_path(r'^student3/(?P<pk>\d+)/$',views.Student6.as_view()), ] # 路由列表
視圖配置
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse,HttpResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list,many=True) print(111,serializer.data) return JsonResponse(serializer.data,safe=False) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data) import json from ser.serializers import Student2Serializer class Student3(View): def post(self,request): #獲取提交數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student2Serializer(data=data_dict) #serializer.is_valid() #出現異常不會報錯 serializer.is_valid(raise_exception=True) serializer.save() print ("Errors",serializer.errors) print (serializer.validated_data) return JsonResponse(serializer.data) class Student4(View): def put(self,request,pk): # 反序列化用戶提交的數據 data = request.body.decode() data_dict = json.loads(data) student_obj = Student.objects.get(pk=pk) # 調用序列化器進行實例化 # 有instance參數,調用save方法,就會調用update方法。 serializer = Student2Serializer(instance=student_obj,data=data_dict) # is_valid在執行的時候,會自動先后調用 字段的內置選項,自定義驗證方法,自定義驗證函數 # 調用序列化器中寫好的驗證代碼 # raise_exception=True 拋出驗證錯誤信息,並阻止代碼繼續往后運行 # 驗證結果 serializer.is_valid(raise_exception=True) # save 表示讓序列化器開始執行反序列化代碼。create和update的代碼 serializer.save() return JsonResponse(serializer.validated_data) from ser.serializers import Student3Serializer class Student5(View): def get(self,request): #獲取所有數據 student_list = Student.objects.all() serializer = Student3Serializer(instance=student_list,many=True) return JsonResponse(serializer.data,safe=False) def post(self,request): #新增一條數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student3Serializer(data=data_dict) #數據檢驗 serializer.is_valid(raise_exception=True) #數據保存 serializer.save() return JsonResponse(serializer.data) class Student6(View): def get(self, request, pk): #獲取一條 student_obj = Student.objects.get(pk=pk) serializer = Student3Serializer(instance=student_obj) return JsonResponse(serializer.data) def put(self, request, pk): # 更新一條數據 data = request.body.decode() data_dict = json.loads(data) student_obj = Student.objects.get(pk=pk) serializer = Student3Serializer(instance=student_obj,data=data_dict) serializer.is_valid(raise_exception=True) serializer.save() return JsonResponse(serializer.data) def delete(self,request,pk): student_obj = Student.objects.get(pk=pk) student_obj.delete() return HttpResponse("Delete Success")
POSTMAN調試
獲取所有
添加一條數據
數據庫查看
修改一條數據
查看數據庫
刪除
結果
查看數據庫
五 模型類序列化器
如果我們想要使用序列化器對應的是Django的模型類,DRF為我們提供了ModelSerializer模型類序列化器來幫助我們快速創建一個Serializer類。
在ser應用下serializers.py文件定義模型類序列化器:
這種基於ModelSerializer聲明序列化器的方式有三個優勢:
1. 可以直接通過聲明當前序列化器中指定的模型中把字段聲明引用過來
2. ModelSerializer是繼承了Serializer的所有功能和方法,同時還編寫update和create
3. 模型中同一個字段中關於驗證的選項,也會被引用到序列化器中一並作為選項參與驗證
from rest_framework import serializers from students.models import Student # 所有的自定義序列化器必須直接或間接繼承於 serializers.Serializer class StudentSerializer(serializers.Serializer): # 聲明序列化器 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] id = serializers.IntegerField() name = serializers.CharField() sex = serializers.BooleanField() age = serializers.IntegerField() class_null = serializers.CharField() description = serializers.CharField() # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] # 4. 可選[ 用於把通過驗證的數據進行數據庫操作,保存到數據庫 ] #自定義函數 def check_user(data): if data == "darren": raise serializers.ValidationError("用戶名不能為darren!") return data class Student2Serializer(serializers.Serializer): #字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4,validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # 2. 可選[ 如果序列化器繼承的是ModelSerializer,則需要聲明對應的模型和字段, ModelSerializer是Serializer的子類 ] # 3. 可選[ 用於對客戶端提交的數據進行驗證 ] #驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs def create(self, validated_data): print(validated_data) name = validated_data.get("name") sex = validated_data.get("sex") age = validated_data.get("age") instance = Student.objects.create(name=name,sex=sex,age=age) #instance = Student.objects.create(**validated_data) return instance #更新數據 def update(self, instance, validated_data): #用於在反序列化中對於驗證完成的數據進行保存更新 instance.name = validated_data.get("name") instance.age = validated_data.get("age") instance.sex = validated_data.get("sex") instance.save() return instance class Student3Serializer(serializers.Serializer): # 字段聲明 # 1. 字段聲明[ 要轉換的字段,當然,如果寫了第二部分代碼,有時候也可以不用寫字段聲明 ] name = serializers.CharField(max_length=10, min_length=4, validators=[check_user]) sex = serializers.BooleanField(required=True) age = serializers.IntegerField(max_value=150, min_value=0) # model #3.數據校驗,驗證單個字段值的合法性 def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate_age(self, data): if data < 18: raise serializers.ValidationError("年齡不能小於18") return data #驗證多個字段值的合法性 def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs def create(self, validated_data): print(validated_data) name = validated_data.get("name") sex = validated_data.get("sex") age = validated_data.get("age") instance = Student.objects.create(name=name,sex=sex,age=age) #instance = Student.objects.create(**validated_data) return instance def update(self, instance, validated_data): #用於在反序列化中對於驗證完成的數據進行保存更新 instance.name = validated_data.get("name") instance.age = validated_data.get("age") instance.sex = validated_data.get("sex") instance.save() return instance #使用model模型類序列化 class Student4ModelSerializer(serializers.ModelSerializer): class Meta: model = Student # fields = "__all__" # 表示引用所有字段 fields = ["id", "name", "age", "class_null", "is_18"] # is_18 為自定制字段,需要在models里自定義方法。 # exclude = ["age"] # 使用exclude可以明確排除掉哪些字段, 注意不能和fields同時使用。 # 傳遞額外的參數,為ModelSerializer添加或修改原有的選項參數 extra_kwargs = { "name": {"max_length": 10, "min_length": 4, "validators": [check_user]}, "age": {"max_value": 150, "min_value": 0}, } def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "renwoxing" and age == 22: raise serializers.ValidationError("任我行已經50多了。。。") return attrs #數據保存,不用自己寫方法,在model已經寫好了creat和update
urls
from rest_framework.routers import DefaultRouter from django.urls import path,re_path from ser import views urlpatterns = [ path('student1/',views.Student1.as_view()), re_path(r'student1/(?P<pk>\d+)/$',views.Student2.as_view()), #數據校驗 path('student2/',views.Student3.as_view()), #修改更新數據 re_path(r'^student2/(?P<pk>\d+)/$',views.Student4.as_view()), #序列化整合使用 path('student3/',views.Student5.as_view()), re_path(r'^student3/(?P<pk>\d+)/$',views.Student6.as_view()), #模型類序列化整合使用 path('student4/',views.Student7.as_view()), re_path(r'^student4/(?P<pk>\d+)/$',views.Student8.as_view()), ] # 路由列表
views視圖
from django.shortcuts import render from django.views import View from students.models import Student from ser.serializers import StudentSerializer from django.http import JsonResponse,HttpResponse # Create your views here. class Student1(View): def get(self,request): """使用序列化器進行數據的序列化操作,序列化器轉換一條數據[模型轉換成字典]""" #獲取所有數據,接收客戶端傳過來的參數,進行過濾查詢,先查出學生對象 student_list = Student.objects.all() #序列化操作 serializer = StudentSerializer(instance=student_list,many=True) print(111,serializer.data) return JsonResponse(serializer.data,safe=False) class Student2(View): def get(self,request,pk): student_obj = Student.objects.get(pk=pk) #序列化操作,StudentSerializer(instance=模型對象或者模型列表,客戶端提交的數據,額外要傳遞到序列化器中使用的數據) serializer = StudentSerializer(instance=student_obj) print(serializer.data) return JsonResponse(serializer.data) import json from ser.serializers import Student2Serializer class Student3(View): def post(self,request): #獲取提交數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student2Serializer(data=data_dict) #serializer.is_valid() #出現異常不會報錯 serializer.is_valid(raise_exception=True) serializer.save() print ("Errors",serializer.errors) print (serializer.validated_data) return JsonResponse(serializer.data) class Student4(View): def put(self,request,pk): # 反序列化用戶提交的數據 data = request.body.decode() data_dict = json.loads(data) student_obj = Student.objects.get(pk=pk) # 調用序列化器進行實例化 # 有instance參數,調用save方法,就會調用update方法。 serializer = Student2Serializer(instance=student_obj,data=data_dict) # is_valid在執行的時候,會自動先后調用 字段的內置選項,自定義驗證方法,自定義驗證函數 # 調用序列化器中寫好的驗證代碼 # raise_exception=True 拋出驗證錯誤信息,並阻止代碼繼續往后運行 # 驗證結果 serializer.is_valid(raise_exception=True) # save 表示讓序列化器開始執行反序列化代碼。create和update的代碼 serializer.save() return JsonResponse(serializer.validated_data) from ser.serializers import Student3Serializer class Student5(View): def get(self,request): #獲取所有數據 student_list = Student.objects.all() serializer = Student3Serializer(instance=student_list,many=True) return JsonResponse(serializer.data,safe=False) def post(self,request): #新增一條數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student3Serializer(data=data_dict) #數據檢驗 serializer.is_valid(raise_exception=True) #數據保存 serializer.save() return JsonResponse(serializer.data) class Student6(View): def get(self, request, pk): #獲取一條 student_obj = Student.objects.get(pk=pk) serializer = Student3Serializer(instance=student_obj) return JsonResponse(serializer.data) def put(self, request, pk): # 更新一條數據 data = request.body.decode() data_dict = json.loads(data) student_obj = Student.objects.get(pk=pk) serializer = Student3Serializer(instance=student_obj,data=data_dict) serializer.is_valid(raise_exception=True) serializer.save() return JsonResponse(serializer.data) def delete(self,request,pk): student_obj = Student.objects.get(pk=pk) student_obj.delete() return HttpResponse("Delete Success") from ser.serializers import Student4Serializer class Student7(View): def get(self, request): # 獲取所有數據 student_list = Student.objects.all() serializer = Student4Serializer(instance=student_list, many=True) return JsonResponse(serializer.data, safe=False) def post(self, request): # 新增一條數據 data = request.body.decode() data_dict = json.loads(data) serializer = Student4Serializer(data=data_dict) # 數據檢驗 serializer.is_valid(raise_exception=True) # 數據保存 serializer.save() return JsonResponse(serializer.data) class Student8(View): def get(self, request, pk): #獲取一條 student_obj = Student.objects.get(pk=pk) serializer = Student4Serializer(instance=student_obj) return JsonResponse(serializer.data) def put(self, request, pk): # 更新一條數據 data = request.body.decode() data_dict = json.loads(data) student_obj = Student.objects.get(pk=pk) serializer = Student4Serializer(instance=student_obj,data=data_dict) serializer.is_valid(raise_exception=True) serializer.save() return JsonResponse(serializer.data) def delete(self,request,pk): student_obj = Student.objects.get(pk=pk) student_obj.delete() return HttpResponse("Delete Success")
使用POSTMAN進行調試,效果一樣
參考: