目錄
- 一、序列化器-serializer
- 二、序列化器的使用
- 高級使用
- source
- **SerializerMethodField( ) **
- 通用參數(shù)
- 三、反序列化數(shù)據(jù)校驗
- 四、序列化器操作數(shù)據(jù)
- 查詢所有
- 查詢單條
- 新增數(shù)據(jù)
- 修改數(shù)據(jù)
- 刪除數(shù)據(jù)
- 五、模型類序列化器
- 六、源碼分析many=True
一、序列化器-serializer
- 序列化,序列化器會把模型對象轉(zhuǎn)成字典,經(jīng)過response以后變成JSON字符串
- 反序列化:把客戶端發(fā)送過來的數(shù)據(jù),經(jīng)過request以后變成字典,序列化器可以把字典轉(zhuǎn)成模型
- 反序列化:完成數(shù)據(jù)校驗功能
二、序列化器的使用
序列化器的使用分為兩個階段:
- 在客戶端請求時,使用序列化器可以完成對數(shù)據(jù)的反序列化。
- 在服務(wù)器響應(yīng)時,使用序列化器可以完成對數(shù)據(jù)的序列化。
簡單使用
1、創(chuàng)建一個表模型
from django.db import models
class Books(models.Model):
title = models.CharField(verbose_name='書名', max_length=32)
publish = models.CharField(verbose_name='出版社', max_length=32)
price = models.DecimalField(verbose_name='價格', max_digits=5, decimal_places=2)
2、新建一個py文件,寫一個序列化的類,繼承Serializer
3、在類中寫要序列化的字段,想序列化那個字段,就在類中寫那個字段
from rest_framework import serializers
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField()
4、在視圖類中使用,導(dǎo)入——》實例化得到序列化對象,把要序列化的對象傳入
5、序列化的對象.data——》是一個字典
6、把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from app01.models import Books
from app01.ser import BooksSerializer
class BookView(APIView):
def get(self, request, pk):
# 響應(yīng)信息
response_msg = {'status': 200, 'message': '查詢成功'}
# 獲取要序列化的對象
book = Books.objects.filter(pk=pk).first()
# 要序列化誰就把誰傳到序列化類去
book_ser = BooksSerializer(book)
# book_ser.data————》序列化對象.data————》就是序列化后的字典
# 將查詢結(jié)果添加到響應(yīng)信息內(nèi)
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
re_path(r'^book/(?Ppk>\d+)/', views.BookView.as_view()),
7、如果要被序列化的是包含多條數(shù)據(jù)的查詢集queryset,可以通過添加many=True參數(shù)
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.models import Books
from app01.ser import BooksSerializer
class BooksView(APIView):
def get(self, request):
# 響應(yīng)信息
response_msg = {'status': 200, 'message': '查詢成功'}
books = Books.objects.all()
# 要序列化誰就把誰傳到序列化類去
book_ser = BooksSerializer(books, many=True)
# book_ser.data————》序列化對象.data————》就是序列化后的字典
# 將查詢結(jié)果添加到響應(yīng)信息內(nèi)
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
re_path(r'^books/', views.BookView.as_view()),
高級使用
source
1、可以修改字段名字
class BooksSerializer(serializers.Serializer):
xxx = serializers.CharField(source='title') # 相當(dāng)于——》xxx = Books.title
# 響應(yīng)
{
"status": 200,
"message": "查詢成功",
"data": {
"xxx": "魔道祖師" ————》響應(yīng)的字段名被修改了
}
}
2、可以跨表查詢
class BookSerializer(serializers.Serializer):
publish_email = serializers.CharField(source='publish.email')
# 相當(dāng)于——》publish_email = Book.publish.email 連表查詢publish表的email字段
# 響應(yīng)
{
"status": 200,
"message": "查詢成功",
"data": {
"publish_email": "modao@163.com"
}
}
3、可以執(zhí)行方法
# models.py
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
pub_date = models.DateTimeField()
publish = models.ForeignKey("Publish", on_delete=models.CASCADE, null=True)
authors = models.ManyToManyField("Author")
def func(self):
return '666666'
# ser.py
class BookSerializer(serializers.Serializer):
msg = serializers.CharField(source='func')
# msg = Book.func ——》調(diào)用Book類中的func()方法的返回值
# 響應(yīng)
{
"status": 200,
"message": "查詢成功",
"data": {
"msg": "666666"
}
}
**SerializerMethodField( ) **
它需要有一個配套的方法,方法名叫做get_字段名,返回值就是要顯示的東西
class BookSerializer(serializers.Serializer):
authors = serializers.SerializerMethodField()
def get_authors(self, instance):
# instance ——》 Book對象
authors = instance.authors.all() # 取出所有作者
author_list = []
for author in authors:
author_list.append({'name': author.name, 'age': author.age})
return author_list
通用參數(shù)
read_only:(只讀)表明該字段僅用于序列化輸出,默認(rèn)False,如果設(shè)置成True,響應(yīng)中可以看到該字段,修改時,不需要傳該字段
write_only:(只寫)表明該字段僅用于反序列化輸入,默認(rèn)False,如果設(shè)置成True,響應(yīng)中看不到該字段,修改時,該字段需要傳
from rest_framework import serializers
class BooksSerializer(serializers.Serializer):
title = serializers.CharField(read_only = True) # 響應(yīng)中能看到改字段,修改不需要傳值
publish = serializers.CharField(write_only = True) # 響應(yīng)中看不到改字段,修改需要傳值
price = serializers.DecimalField()
還有參數(shù)如下:
- required 表明該字段在反序列化時必須輸入,默認(rèn)True
- default 反序列化時使用的默認(rèn)值
- allow_null 表明該字段是否允許傳入None,默認(rèn)False
- validators 該字段使用的驗證器
- error_messages 包含錯誤編號與錯誤信息的字典
三、反序列化數(shù)據(jù)校驗
當(dāng)使用序列化器對數(shù)據(jù)進(jìn)行反序列化時,就需要對數(shù)據(jù)進(jìn)行校驗了,只有校驗成功的數(shù)據(jù)才能被保存成模型類對象
將要校驗的數(shù)據(jù)傳入序列化器中并實例化:obj = BooksSerializer(data=request.data),調(diào)用is_valid()方法校驗,校驗成功返回True,失敗返回False。
失敗,可以通過序列化器對象的errors獲取錯誤信息(字典)
成功,可以公共序列化對象的validated_data屬性獲取數(shù)據(jù)。
校驗方法有:局部鉤子,全局鉤子,validators,和序列化類型和字段屬性也是
字段屬性
- max_length 最大長度
- min_lenght 最小長度
- allow_blank 是否允許為空
- trim_whitespace 是否截斷空白字符
- max_value 最小值
- min_value 最大值
局部鉤子
在序列化器類中創(chuàng)建局部鉤子:validate_字段名,并且接收一個參數(shù)
# ser.py
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
# 局部鉤子對price字段校驗
def validate_price(self, data):
if float(data) > 20:
# 校驗成功就通過
return data
else:
# 校驗失敗就拋異常
raise ValidationError('價格太低')
全局鉤子
全局鉤子:validate( ), 接收一個參數(shù),
同時對多個字段進(jìn)行比較驗證
# ser.py
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
def validate(self, validate_data):
title = validate_data.get('title')
publish = validate_data.get('publish')
if not title == publish:
return validate_data
else:
raise ValidationError('書名和出版社不能一致')
validators
使用字段的validators=[func],來校驗
# ser.py
# 校驗函數(shù)
def check_price(data):
if float(data) > 10:
return data
else:
raise ValidationError('價格太低')
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.CharField(validators=[check_price]) # 配置
四、序列化器操作數(shù)據(jù)
查詢所有
# views.py
class BooksView(APIView):
def get(self, request):
# 響應(yīng)信息
response_msg = {'status': 200, 'message': '查詢成功'}
# 獲取所有數(shù)據(jù)
books = Books.objects.all()
# 把數(shù)據(jù)誰傳到序列化器中
book_ser = BooksSerializer(instance=books, many=True) # 序列化多條需要加 many=True
# book_ser.data————》序列化對象.data————》就是序列化后的字典
# 將查詢結(jié)果添加到響應(yīng)信息內(nèi)
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
path('books/', views.BooksView.as_view()),
查詢單條
# views.py
class BookView(APIView):
def get(self, request, pk):
# 響應(yīng)信息
response_msg = {'status': 200, 'message': '查詢成功'}
# 獲取要序列化的對象
book = Books.objects.filter(pk=pk).first()
# 要序列化誰就把誰傳到序列化器中
book_ser = BooksSerializer(instance=book)
# book_ser.data————》序列化對象.data————》就是序列化后的字典
# 將查詢結(jié)果添加到響應(yīng)信息內(nèi)
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
re_path(r'^book/(?Ppk>\d+)/', views.BookView.as_view()),
新增數(shù)據(jù)
新增數(shù)據(jù)需要在序列化器中重寫create( ) 方法:
注意沒有傳遞instance實例,則調(diào)用save()方法的時候,create()被調(diào)用,相反,如果傳遞了instance實例,調(diào)用save()方法的時候,update()被調(diào)用。
# views.py
class BookView(APIView):
def post(self, request):
# 響應(yīng)信息
response_msg = {'status': 201, 'message': '增加成功'}
# 修改才有instance,新增沒有instance,只有data
book_ser = BooksSerializer(data=request.data)
# 校驗字段
if book_ser.is_valid():
book_ser.save() # 需要在序列化器中重寫create()方法
# 保存成功把原數(shù)據(jù)返回
response_msg['data'] = book_ser.data
else:
response_msg['status'] = 202
response_msg['message'] = '數(shù)據(jù)校驗失敗'
response_msg['data'] = book_ser.error_messages
return Response(response_msg)
# ser.py
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
# 重寫create
def create(self, validated_data): # validated_data——>傳入的新增數(shù)據(jù)
instance = Books.objects.create(**validated_data)
# instance——> 新增的字段對象,需要返回
return instance
# urls.py
path('book/', views.BookView.as_view()),
修改數(shù)據(jù)
修改數(shù)據(jù)需要在序列化器中重寫update( ) 方法:
# views.py
class BookView(APIView):
def put(self, request, pk):
# 響應(yīng)信息
response_msg = {'status': 200, 'message': '修改成功'}
# 獲取需要修改的字段對象
book = Books.objects.filter(pk=pk).first()
# 將字段對象和修改數(shù)據(jù)添加到序列化器中
book_ser = BooksSerializer(instance=book, data=request.data)
# 校驗數(shù)據(jù)
if book_ser.is_valid():
book_ser.save() # 需要在序列化器中重寫update()方法
response_msg['data'] = book_ser.data
else:
response_msg['status'] = 202
response_msg['message'] = '數(shù)據(jù)校驗失敗'
response_msg['data'] = book_ser.error_messages
return Response(response_msg)
# urls.py
re_path('book/(?Ppk>\d+)', views.BookView.as_view()),
刪除數(shù)據(jù)
# views.py
class BooksView(APIView):
def delete(self, request, pk):
# 響應(yīng)信息
response_msg = {'status': 200, 'message': '刪除成功'}
# 刪除數(shù)據(jù)
Books.objects.filter(pk=pk).delete()
return Response(response_msg)
# urls.py
re_path('book/(?Ppk>\d+)', views.BooksView.as_view()),
五、模型類序列化器
DRF提供了ModelSerializer模型類序列化器來幫助我們快速創(chuàng)建一個Serializer類。
ModelSerializer與常規(guī)的Serializer相同,但是提供了:
- 基于模型類自動生成一系列字段
- 基于模型類自動為Serializer生成validators,比如unique_together
- 包含默認(rèn)的create( ) 和update( )。
實例:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book # 指明參照那個模型類
fields = '__all__' # 為模型類的那些字段生成
字段操作
1、可以使用fields來明確字段,__all__表示包含所以字段,具體那些字段->fields = ('title','price')
2、exclude表示排除那些字段,不能和fields一起寫——>exclude = ('price',)
3、額外參數(shù)extra_kwargs,給字段添加額外的參數(shù)
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book # 指明參照那個模型類
fields = '__all__' # 為模型類的那些字段生成
# 類似于 title = serializers.CharField(read_only = True)
extra_kwargs = {
'title': {'read_only': True},
}
六、源碼分析many=True
當(dāng)我們需要查詢多條數(shù)據(jù)時就需要在實例化序列化器的時候傳many=True
book_ser = BooksSerializer(instance=books, many=True) # 查詢多條
book_one_ser = BooksSerializer(instance=book) # 查詢單條
print(type(book_ser))
#class 'rest_framework.serializers.ListSerializer'>
print(type(book_one_ser))
#class 'app01.ser.BookModelSerializer'>
# 對象的生成-->先調(diào)用類的__new__方法,生成空對象,如果many=True,生成ListSerializer對象,反之生成Serializer對象
# 類的__new__方法控制對象的生成
def __new__(cls, *args, **kwargs):
# 如果many=True,就會自動創(chuàng)建ListSerializer類
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super().__new__(cls, *args, **kwargs)
到此這篇關(guān)于drf序列化器serializer的具體使用的文章就介紹到這了,更多相關(guān)drf序列化器serializer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- DRF跨域后端解決之django-cors-headers的使用
- django DRF圖片路徑問題的解決方法
- Django框架之DRF 基于mixins來封裝的視圖詳解
- DRF使用simple JWT身份驗證的實現(xiàn)
- Django DRF APIView源碼運(yùn)行流程詳解
- python drf各類組件的用法和作用
- DRF框架API版本管理實現(xiàn)方法解析
- Django drf請求模塊源碼解析