rest framework serializer 深入理解
這篇主要是記錄一些個人對於rest framework的serializer源碼實作的理解,從下段源碼
1 |
|
可以看到作為ModelSerializer還有一些xxSerializer的base class(Serializer),是繼承BaseSerializer,以及還有個metaclass,首先我們就先來看看meta class這邊,它用到了six這個third party library,這模組主要目的是幫你弄出python2和3 compatible的code,`@six.add_metaclass`這個東西作用如下,
1 |
|
至於對於metaclass的作用,這邊我不多加敘述,詳情可以看我之前的blog,有篇是對於metaclass的理解,SerializerMetaclass做的事情,基本上是在我們new instance時,把attribute屬於Field的instance給濾出來~ 這個Field是rest framework fields.py裡面有所定義,濾出來後呢,接著按照_creation_counter來排序,之後把這些給assgin到_declared_fields
看到這邊目前不知道為什麼要作這個動作,不過我相信我們繼續看下去應該就會知道為什麼了? 這個metaclass做的事情就是這樣而已。
接著由於BaseSerializer是繼承Field,所以我們先來看看Field是作什麼
1 |
|
關於init函式,一些需要注意的地方我都寫在註解上面了,當然有些參數目前還不知道是要做啥,但是不明的東西就先打個問號,因為你在怎麼執著於這邊,你也不知道答案是什麼,必須要看到其他地方式怎麼使用這些參數的或函式,才會比較明瞭,所以姑且就繼續往下看吧
1 |
|
單單這樣看好像挺模糊的,他的assert希望 self.source 和 field_name 一樣,可是好玩的是假如self.source是None的話,self.source = field_name,所以這邊我有點不懂她是在assert啥…
再來下面四個method,就比較簡單了,
1 |
|
雖然我個人覺得啦,她分的好細,乍看之下或許有點多餘,不過看久了到是覺得還好,反正邏輯很簡單,只要沒有做過 self.validators = …. 那她就會使用 self.default_validators[:] 來回傳結果~
1 |
|
這裡html.is_html_input,是做一個檢查,是什麼呢? 她檢查 dictionary是否擁有 getlist 這個屬性,很好,值得注意的是這裡的dictionary,似乎是因為有可能會是django的MultiValueDict,這個就會有getlist這個屬性了,相信之後部份code會用到這個method,讓我們就先繼續往下走~~
1 |
|
這裡有call一個global get_attribue 這個之後看,當發生exception(KeyError, AttribueError)時,這裡做的處理是如果此field非required和default是empty的話,就會raise SkipField(),要不然就是照樣raise該有的錯誤,只是給她額外增加一個比較fancy的錯誤訊息。再來讓我們瞧瞧global的get_attribue到底做了什麼!
1 |
|
還記得前面bind
method做了什麼好事嗎?
1 | if self.source == '*': |
由於經過這樣的處理,所以attrs必定是list型態,所以這邊get_attribute
才會用for loop,其實這個function做的事情,如同他的註解說的差不多,真的就跟python內建的 getattr
很像,只是他可以接受nested屬性,例如: obj.a.c
這樣。
1 |
|
這兩個function就不多琢磨了,就算是helper function這樣
1 | def run_validation(self, data=empty): |
這邊就是serializer常用到的validation了,做檢查~
最後值得注意的地方是下面這兩個function
1 |
|
to_internal_value
作用就是把輸入得資料轉換成,你資料庫或者其他地方你想要儲存的型態,像是日期好了,你輸入的是字串,但是rest framework的DatetimeField,是幫你轉成python裡的datetime相關物件, 至於 to_representation
就是資料輸出的形式, 一般都是當你call serializer.data
所表現的形式就是用到上面那個function, 這裡的serializer是某某Serializer class的instance。
到目前為止,class Field,大致上的實作都大概看過了,這個是很重要的核心,因為你看源碼你會發現,有很多其他東西都是繼承於這個, XXXField 一堆~~
這篇就先紀錄到這邊為止,下一次就回到BaseSerializer那邊去理解源碼。