這里的介紹的serializers.ModelSerializer就和我們之前學習的modelform一樣
serializers.ModelSerializer如下幾個功能
1、序列化queryset數據
2、反序列化json數據,將反序列化后的數據轉換成model對象
3、反序列化的時候還是可以對數據做校驗
4、如果合法,可以調用sava方法進行post或者put請求操作
5、如果不合法,則返回錯誤
下面我們進入serializers.ModelSerializer的學習
首先寫一個modelserializer的類,不知道看官有沒有發現,和我們之前學的modelform幾乎完全一樣
class bookmodelserializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__"
然后我們在get請求中,如何通過上面的類序列化queryset對象,可以看到直接之前的serializer類替換為modelserializer類就可以了
from rest_framework.views import APIView
from rest_framework.response import Response
class Book_cbv(APIView):
def get(self,request):
query_list = models.Book.objects.all()
# bs = book_serializers(query_list,many=True)
bs = bookmodelserializer(query_list,many=True)
print(dir(serializers))
return Response(bs.data)
通過postman發送get請求,我們看下受到的信息,我們看到一對多字段和多對多字段均為所對應對象的id,我們可以定制化的顯示我們需要顯示的信息,但是這里暫時不做講解,在博客的后面我們在做講解

上面處理完了get請求,下面我們在處理一下post請求,我們通過postman發送json信息,然后通過modelserializerlizer直接保存信息,post請求處理的代碼如下
如何數據有效,則保存數據,這個也和modelform非常的類型,可以說是完全一樣
def post(self,request):
bs = bookmodelserializer(data=request.data)
if bs.is_valid():
print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return Response(bs.errors)
下面我們通過postman發送post請求,測試一下

發送完post請求,我們看下返回的結果,將我們的新增的數據返回了

至此,modelserializar的基本用法我們就講完了
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面我們開始定制化的處理
首先,在get請求中,對於一對多和多對多的字段,我們想定制化的顯示,那么我們就可以這樣做
class bookmodelserializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__"
# 一對多,關聯指定的對象,然后顯示指定對象的字段
book_publish = serializers.CharField(source="book_publish.id")
book_auther = serializers.SerializerMethodField()
def get_book_auther(self,obj):
s = ""
for i in obj.book_auther.all():
s = s + i.auther_name + "|"
s = s.rstrip("|")
return s
重點是這里,就是serializer中處理一對多和多對多的代碼拿過來就可以了

下面我們通過postman發送get請求,看下前端的顯示效果,看到效果,已經實現了我們的想要的結果

上面解決了定制化的處理get請求,那么post請求行不行呢?
我們直接使用postman來做一下測試

我們看到有報錯,其實的modelserializer這個類的create方法無法處理這種定制的話的數據
下面的是modelserializer類的create方法
def create(self, validated_data):
"""
We have a bit of extra checking around this in order to provide
descriptive messages when something goes wrong, but this method is
essentially just:
return ExampleModel.objects.create(**validated_data)
If there are many to many fields present on the instance then they
cannot be set until the model is instantiated, in which case the
implementation is like so:
example_relationship = validated_data.pop('example_relationship')
instance = ExampleModel.objects.create(**validated_data)
instance.example_relationship = example_relationship
return instance
The default implementation also does not handle nested relationships.
If you want to support writable nested relationships you'll need
to write an explicit `.create()` method.
"""
raise_errors_on_nested_writes('create', self, validated_data)
ModelClass = self.Meta.model
# Remove many-to-many relationships from validated_data.
# They are not valid arguments to the default `.create()` method,
# as they require that the instance has already been saved.
info = model_meta.get_field_info(ModelClass)
many_to_many = {}
for field_name, relation_info in info.relations.items():
if relation_info.to_many and (field_name in validated_data):
many_to_many[field_name] = validated_data.pop(field_name)
try:
instance = ModelClass._default_manager.create(**validated_data)
except TypeError:
tb = traceback.format_exc()
msg = (
'Got a `TypeError` when calling `%s.%s.create()`. '
'This may be because you have a writable field on the '
'serializer class that is not a valid argument to '
'`%s.%s.create()`. You may need to make the field '
'read-only, or override the %s.create() method to handle '
'this correctly.\nOriginal exception was:\n %s' %
(
ModelClass.__name__,
ModelClass._default_manager.name,
ModelClass.__name__,
ModelClass._default_manager.name,
self.__class__.__name__,
tb
)
)
raise TypeError(msg)
# Save many-to-many relationships after the instance is created.
if many_to_many:
for field_name, value in many_to_many.items():
field = getattr(instance, field_name)
field.set(value)
return instance
因為我們的對象是繼承了modelserializer類,所以我們重寫一下create方法,就可以解決這個問題,因為如果我們的類中有create方法,會優先調用我們自己的create方法,只有當我們的類中沒有create方法,才會去調用父類的create方法
首先我們在自己的類中定義一個create方法,先打印參數看看
class bookmodelserializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__"
# 一對多,關聯指定的對象,然后顯示指定對象的字段
def create(self, validated_data):
print(validated_data)
book_publish = serializers.CharField(source="book_publish.id")
book_auther = serializers.SerializerMethodField()
def get_book_auther(self,obj):
s = ""
for i in obj.book_auther.all():
s = s + i.auther_name + "|"
s = s.rstrip("|")
return s
create方法我們下截圖出來

我們再次通過postman發送post請求,看下打印的結果
這里我無論如何怎么處理,在新的create方法中均無法打印出book_auther的數據,我也是很納悶
無論我在上面的函數中返回一個字符串,還是一個list,都不行
上面這一行是reqeust.data中的數據,下面這一行是validated_data中的數據

那么我暫時把多對多中的定制化處理注銷掉,用默認的方式顯示把
class bookmodelserializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__"
# 一對多,關聯指定的對象,然后顯示指定對象的字段
def create(self, validated_data):
print("validated_data",validated_data)
# models.Book.objects.create(
# book_name = validated_data
# )
book_publish = serializers.CharField(source="book_publish.id")
# book_auther = serializers.SerializerMethodField()
# def get_book_auther(self,obj):
#
# s = []
# for i in obj.book_auther.all():
# s.append(i)
#
#
# return s
這次我們通過postman發送post請求

這次validated_data中就有book_auther信息就了

然后我們調用create方法在數據庫中創建數據就可以了
class bookmodelserializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__"
# 一對多,關聯指定的對象,然后顯示指定對象的字段
def create(self, validated_data):
print("validated_data",validated_data)
ret = models.Book.objects.create(
book_name = validated_data["book_name"],
book_price = validated_data["book_price"],
book_publish_id = validated_data["book_publish"]["id"]
)
ret.book_auther.add(*validated_data["book_auther"])
return ret
這個時候我們在通過postman發送post請求,可以看到創建數據成功了

至於定制化的多對多字段,我下來在研究一下,今天太晚了,明天還得上班!
