序列化元件serializer基本使用
阿新 • • 發佈:2020-07-19
目錄
- 1. 序列化元件使用原理
- 2. 序列化元件serializer的簡單使用
- 3.序列化元件使用 --- 序列化之查詢指定id書籍的介面
- 4. 序列化元件使用---反序列化之修改資料
- 5. 刪除資料
- 6. 序列化查詢所有所有書籍
- 7. 反序列化 --- 新增書籍
- 8. 模型類序列化器
- 9. many=True的原始碼分析
- 10. Serializer高階用法
- 11. 簡單封裝Response物件返回的狀態碼資訊
- 補充
1. 序列化元件使用原理
- 序列化,序列化器會把模型物件轉換成字典,經過response以後變成json字串
- 反序列化,把客戶端傳送過來的資料,經過request以後變成字典,序列化器可以把字典轉成模型
- 反序列化,完成資料校驗功能
2. 序列化元件serializer的簡單使用
寫一個序列化類
在類中寫要序列化的欄位,想序列化哪個欄位,就在類中寫哪個欄位
在檢視類中匯入該序列化類,例項化序列化類得到序列化類的物件,將需要序列化的物件傳入
序列化類的物件.data 是一個字典
把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse
3.序列化元件使用 --- 序列化之查詢指定id書籍的介面
- 準備書籍表
from django.db import models class Book(models.Model): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) publish = models.CharField(max_length=32)
- 建立任意名稱的py檔案,在該檔案中建立序列化類,該序列化類需要繼承APIView
from rest_framework.views import APIView
from rest_framework import seriaizers
class BookSerializer(serializers.Serializer):
id = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
- 在views.py中建立檢視類,並使用自定義的序列化類對資料進行序列化,使用rest_framework的Response返回資料
from app01.ser import BookSerializer
from app01 import models
class BookView(APIView):
def get(self,request,pk):
dic = {'code':100,'status':'成功'}
book = models.Book.objects.filter(pk=pk).first()
book_ser = BookSerializer(book)
dic['data'] = book_ser.data
return Response(dic)
- 在urls.py中寫好路由與檢視類的對應關係
re_path(r'^book/(?P<pk>\d+)',views.BookView.as_view()),
4. 序列化元件使用---反序列化之修改資料
- 需要在序列化類中定義校驗規則,如果客戶端返回給後端的資料符合校驗規則,就需要將資料儲存到資料庫,當資料通過校驗的時候,如果不在序列化類中重寫update方法就會丟擲異常
# 序列化類檔案
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
# 校驗規則也可以寫在序列化類的外面,哪個欄位需要這個校驗規則就加入到哪個欄位的後面,使用validators=[check_book,]的格式
def check_book(data):
# data是瀏覽器客戶端傳過來的對應的欄位的資料,因為該方法加在了name欄位後面,所以data就是瀏覽器傳到後端的name
print(data)
class BookSerializer(serializers.Serializer):
id = serializers.CharField(read_only=True)
name = serializers.CharField(validators=[check_book,])
price = serializers.CharField()
publish = serializers.CharField()
# 區域性校驗,適用於單個欄位
def validate_name(self, instance):
# instance是瀏覽器返回的要修改的資料
if instance.startswith('xxx'):
raise ValidationError('不能以xxx開頭')
else:
return instance
# 全域性校驗,適用於多個欄位的校驗
def validate(self, attrs):
# attrs是客戶端要返回給後端的資料物件
if attrs.get('name') == attrs.get('publish'):
raise ValidationError('二者不能相同')
else:
return attrs
# 重寫update方法
def update(self, instance, validated_data):
'''
:param instance: 修改的物件
:param validated_data: 更新的資料
:return:
'''
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
return instance
# 檢視檔案
class BookView(APIView):
。...
def put(self,request,pk):
dic = {'code':100,'status':''}
book = models.Book.objects.filter(pk=pk).first()
# instance是修改的物件,data是瀏覽器客戶端返回的資料
book_ser = BookSerializer(instance=book,data=request.data)
# 判斷資料是否通過校驗
if book_ser.is_valid():
# 如果資料通過校驗就需要在序列化類中重寫update方法
book_ser.save()
dic['status'] = '修改成功'
dic['data'] = book_ser.data
else:
dic['status'] = '修改失敗'
dic['data'] = book_ser.errors
return Response(dic)
5. 刪除資料
刪除資料無需使用序列化元件
def delete(self,request,pk):
dic = {'code':100,'status':''}
book = models.Book.objects.filter(pk=pk).delete()
dic['status'] = '刪除成功'
return Response(dic)
6. 序列化查詢所有所有書籍
在序列化資料的時候,需要指定many=True,因為查到的資料是多條
def get(self,request):
books = models.Book.objects.all()
book_ser = BookSerializer(books,many=True)
return Response(book_ser.data)
7. 反序列化 --- 新增書籍
新增書籍需要通過序列化類的校驗,並且需要重寫create方法
# 序列化類
# 重寫update方法
def update(self, instance, validated_data):
'''
:param instance: 修改的物件
:param validated_data: 更新的資料
:return:
'''
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
return instance
def create(self,validated_data):
# 客戶端新增的資料是一個字典
print(validated_data)
instance = models.Book.objects.create(**validated_data)
return instance
# views.py
def post(self,request):
# 增加資料,data是客戶端返回給服務端的使用者資料物件
dic = {'code':100,'status':''}
book_ser = BookSerializer(data=request.data)
if book_ser.is_valid():
book_ser.save()
book_ser.save()
dic['data'] = book_ser.data
else:
dic['data'] = book_ser.errors
return Response(dic)
8. 模型類序列化器
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model=Book # 對應上models.py中的模型
fields='__all__' # models中的所有欄位
# fields=('name','price','id','author') # 只序列化指定的欄位
# exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
# read_only_fields=('price',)
# write_only_fields=('id',) #棄用了,使用extra_kwargs
extra_kwargs = { # 類似於這種形式name=serializers.CharField(max_length=16,min_length=4)
'price': {'write_only': True},
}
# 其他使用一模一樣
#不需要重寫create和updata方法了
9. many=True的原始碼分析
序列化多條資料的時候需要傳many=True。
book_ser=BookModelSerializer(books,many=True)
book_one_ser=BookModelSerializer(book)
print(type(book_ser))
#<class 'rest_framework.serializers.ListSerializer'>
print(type(book_one_ser))
#<class 'app01.ser.BookModelSerializer'>
'''
物件的生成--》先呼叫類的__new__方法,生成空物件
物件=類名(name=lqz),觸發類的__init__()
類的__new__方法控制物件的生成
'''
def __new__(cls, *args, **kwargs):
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
# 沒有傳many=True,走下面,正常的物件例項化
return super().__new__(cls, *args, **kwargs)
10. Serializer高階用法
# source的使用
1 可以改欄位名字 xxx=serializers.CharField(source='title')
2 可以.跨表publish=serializers.CharField(source='publish.email')
3 可以執行models表中的方法pub_date=serializers.CharField(source='test') test是Book表模型中的方法
# SerializerMethodField()的使用,當表關係是多對多的關係的欄位
它需要有個配套方法,方法名叫get_欄位名,返回值就是要顯示的東西
authors=serializers.SerializerMethodField() #它需要有個配套方法,方法名叫get_欄位名,返回值就是要被序列化的資料
def get_authors(self,instance):
# book物件
authors=instance.authors.all() # 取出所有作者
l = []
for author in authors:
l.append({'name':author.name,'age':author.age})
return l
11. 簡單封裝Response物件返回的狀態碼資訊
class MyResponse():
def __init__(self):
self.status=100
self.msg='成功'
@property
def get_dict(self):
return self.__dict__
if __name__ == '__main__':
res=MyResponse()
res.status=101
res.msg='查詢失敗'
# res.data={'name':'lqz'}
print(res.get_dict)
補充
- 序列化類的欄位型別
欄位 | 欄位構造方式 |
---|---|
BooleanField | BooleanField() |
NullBooleanField | NullBooleanField() |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正則欄位,驗證正則模式 [a-zA-Z0-9-]+ |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
UUIDField | UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
IPAddressField | IPAddressField(protocol=’both’, unpack_ipv4=False, **options) |
IntegerField | IntegerField(max_value=None, min_value=None) |
FloatField | FloatField(max_value=None, min_value=None) |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位數 decimal_palces: 小數點位置 |
DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
DurationField | DurationField() |
ChoiceField | ChoiceField(choices) choices與Django的用法相同 |
MultipleChoiceField | MultipleChoiceField(choices) |
FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ListField | ListField(child=, min_length=None, max_length=None) |
DictField | DictField(child=) |
- 序列化欄位選項引數
引數名稱 | 作用 |
---|---|
max_length | 最大長度 |
min_lenght | 最小長度 |
allow_blank | 是否允許為空 |
trim_whitespace | 是否截斷空白字元 |
max_value | 最小值 |
min_value | 最大值 |
- 序列化欄位通用引數
引數名稱 | 說明 |
---|---|
read_only | 表明該欄位僅用於序列化輸出,預設False,如果設定成True,postman中可以看到該欄位,修改資料時不需要傳該欄位 |
write_only | 表明該欄位僅用於反序列化輸入,預設False,如果設定成True,postman中看不到該欄位,修改時,該欄位需要傳 |
required | 表明該欄位在反序列化時必須輸入,預設True |
default | 反序列化時使用的預設值 |
allow_null | 表明該欄位是否允許傳入None,預設False |
validators | 該欄位使用的驗證器 |
error_messages | 包含錯誤編號與錯誤資訊的字典 |
label | 用於HTML展示API頁面時,顯示的欄位名稱 |
help_text | 用於HTML展示API頁面時,顯示的欄位幫助提示資訊 |