這裏的介紹的serializers.ModelSerializer就和咱們以前學習的modelform同樣前端
serializers.ModelSerializer以下幾個功能python
一、序列化queryset數據數據庫
二、反序列化json數據,將反序列化後的數據轉換成model對象json
三、反序列化的時候仍是能夠對數據作校驗app
四、若是合法,能夠調用sava方法進行post或者put請求操做ide
五、若是不合法,則返回錯誤函數
下面咱們進入serializers.ModelSerializer的學習post
首先寫一個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請求,能夠看到建立數據成功了
至於定製化的多對多字段,我下來在研究一下,今天太晚了,明天還得上班!