前面學習Serializers用法時,發現所有的序列化都與我們的模型緊密相關。
django_restframework也給我提供了跟模型緊密相關的序列化器——ModelSerializer。
它會根據模型自動生成一組字段;它簡單的默認實現了.update()以及.create()方法。
一、ModelSerializer序列化
1、定義ModelSerializer序列化器
# 針對models設計和聲明序列化類 from rest_framework import serializers from .models import Book, Publisher class BookSerializer(serializers.ModelSerializer): class Meta: model = Book # 與Book表對應 # 這三種情況不能同時使用 # 1.取全部字段 fields = "__all__" # 2.自定義包含字段 # fields = ["id", "title", "pub_time"] # 輸出:[{"id": 1, "title": "python開發", "pub_time": "2011-08-27"},...] # 3.排除某些字段 # exclude = ["id", "category","author", "publisher"] # 輸出:[{"title": "python開發", "pub_time": "2011-08-27"},...]
需要注意的是:取全部字段、取自定義字段、排除某些字段這三種篩選不能同時使用。
2、外鍵關系的序列化
注意:當序列化類META定義了depth時,這個序列化類中引用字段(外鍵)則自動變為只讀。
depth 代表找嵌套關系的第幾層。
class BookSerializer(serializers.ModelSerializer): class Meta: model = Book # 與Book表對應 fields = "__all__" depth = 1
添加depth前,顯示效果:

添加depth后,顯示效果:
由上圖可知,只會查看嵌套深度一層的內容。
3、自定義字段
很多字段默認顯示的是選擇的key值,但要給用戶展示的是value值。
因此可以聲明一些字段來覆蓋默認字段來進行自定制。
class BookSerializer(serializers.ModelSerializer): category = serializers.CharField(source="get_category_display") # 找到對應中文 class Meta: model = Book # 與Book表對應 fields = "__all__"
顯示效果如下所示:

4、Meta中其他關鍵字參數
官方文檔地址:https://www.django-rest-framework.org/api-guide/serializers/
(1)指定只讀字段
希望將多個字段指定為只讀。推薦使用快捷的Meta選項read_only_fields,而不是顯式地使用read_only=True屬性添加每個字段。示例如下所示:
class BookSerializer(serializers.ModelSerializer): chapter = serializers.CharField(source="get_chapter_display", read_only=True) class Meta: model = Book fields = "__all__" depth = 1 read_only_fields = ["id"]
模型字段有設置 editable=False, AutoField 字段默認設置為只讀,不需要添加到 read_only_fields 選項。
(2)給字段添加額外參數——extra_kwargs
使用extra_kwargs參數為ModelSerializer添加或修改原有的選項參數---字典格式。
# 示例一: class BookSerializer(serializers.ModelSerializer): chapter = serializers.CharField(source="get_chapter_display", read_only=True) class Meta: model = Book fields = "__all__" depth = 1 read_only_fields = ["id"] extra_kwargs = {"title": {"validators": [my_validate,]}} # 示例二: class CreateUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['email', 'username', 'password'] extra_kwargs = {'password': {'write_only': True}}
如果字段已在序列化程序類中顯式聲明,則該extra_kwargs選項將被忽略。
5、post和patch請求
由於depth會讓外鍵變成只讀,所以定義一個序列化的類,其實只要去掉depth就可以了。
class BookSerializer(serializers.ModelSerializer): chapter = serializers.CharField(source="get_chapter_display", read_only=True) class Meta: model = Book fields = "__all__" # fields = ["id", "title", "pub_time"] # exclude = ["user"] # 分別是所有字段 包含某些字段 排除某些字段 read_only_fields = ["id"] extra_kwargs = {"title": {"validators": [my_validate,]}}
6、SerializerMethodField
外鍵關聯的對象有很多字段是用不到的,都傳給前端會有數據冗余。需要自己去定制序列化外鍵對象的那些字段。
# 針對models設計和聲明序列化類 from rest_framework import serializers from .models import Book, Publisher class BookSerializer(serializers.ModelSerializer): category = serializers.CharField(source="get_category_display") # 找到對應中文 class Meta: model = Book # 與Book表對應 fields = "__all__"
查看頁面 http://127.0.0.1:8000/books/list,顯示效果如下所示:

添加 SerializerMethodField的使用,獲取顯示外聯字段:
class BookSerializer(serializers.ModelSerializer): category = serializers.CharField(source="get_category_display") # 找到對應中文 # SerializerMethodField的使用,獲取顯示外聯字段 publisher = serializers.SerializerMethodField() author= serializers.SerializerMethodField() def get_author(self, obj): authors_query_set = obj.author.all() # 拿到所有作者信息 return [{"id": authors_obj.id, "name": authors_obj.name} for authors_obj in authors_query_set] # 列表推導式 def get_publisher(self, obj): # obj是我們序列化的每個Book對象 publisher_obj = obj.publisher # 正向查詢 return {'id': publisher_obj.id} class Meta: model = Book # 與Book表對應 fields = "__all__"
顯示效果如下所示:

二、ModelSerializer反序列化
1、ModelSerializer原生POST請求
再將 SerDemo/serializers.py 下 BookSerializer 恢復為原生狀態:
class BookSerializer(serializers.ModelSerializer): class Meta: model = Book # 與Book表對應 fields = "__all__"
不用自定義create方法,可直接提交提交post請求如下:

數據新增成功,如下所示:

2、SerializerMethodField改寫
class BookSerializer(serializers.ModelSerializer): # SerializerMethodField的使用,獲取顯示外聯字段 category_display = serializers.SerializerMethodField(read_only=True) # 重新定義,避免重寫,影響反序列化 publisher_info = serializers.SerializerMethodField(read_only=True) authors = serializers.SerializerMethodField(read_only=True) def get_category_display(self, obj): return obj.get_category_display() # ORM方法獲取中文 def get_authors(self, obj): authors_query_set = obj.author.all() # 拿到所有作者信息 return [{"id": authors_obj.id, "name": authors_obj.name} for authors_obj in authors_query_set] # 列表推導式 def get_publisher_info(self, obj): # obj是我們序列化的每個Book對象 publisher_obj = obj.publisher # 正向查詢 return {'id': publisher_obj.id} class Meta: model = Book # 與Book表對應 fields = "__all__"
顯示效果如下所示:

可以從上圖看到,除了顯示了category_display、authors、publisher_info,也顯示了category、publisher、author。
3、extra_kwargs配置字段參數
class BookSerializer(serializers.ModelSerializer): # SerializerMethodField的使用,獲取顯示外聯字段 category_display = serializers.SerializerMethodField(read_only=True) # 重新定義,避免重寫,影響反序列化 publisher_info = serializers.SerializerMethodField(read_only=True) authors = serializers.SerializerMethodField(read_only=True) def get_category_display(self, obj): return obj.get_category_display() # ORM方法獲取中文 def get_authors(self, obj): authors_query_set = obj.author.all() # 拿到所有作者信息 return [{"id": authors_obj.id, "name": authors_obj.name} for authors_obj in authors_query_set] # 列表推導式 def get_publisher_info(self, obj): # obj是我們序列化的每個Book對象 publisher_obj = obj.publisher # 正向查詢 return {'id': publisher_obj.id} class Meta: model = Book # 與Book表對應 fields = "__all__" extra_kwargs = { "category": {"write_only": True}, # 避免直接改寫 "publisher": {"write_only": True}, "author": {"write_only": True} }
如此就不再顯示category、publisher、author了,顯示效果如下所示:

三、Serializer與ModelSerializer區別

