14镣陕、Django_rest framework_ModelSerializer

一、進一步封裝優(yōu)化序列化器

  • 注意:更高一級的封裝姻政,代表著更少的代碼呆抑,也代表著更低的可定制型
  • 要講訴的方法,類似Django原生的ModelFormmodel的引用

二汁展、ModelSerializer

  • ModelSerializer類能夠讓我們自動你創(chuàng)建一個具有對應模型類中鹊碍,相對應字段的Serializer
  • ModelSerializer類直接繼承了Serializer類,不同的是:
    1.它根據(jù)model模型的定義食绿,自動生成默認字段侈咕。
    2.它自動生成序列化器的驗證器,比如unique_together驗證器器紧。
    3.它實現(xiàn)了簡單的.create()方法和.update()方法耀销。
  • 聲明一個ModelSerializer類,(用之前寫好的序列化器示例铲汪,注釋之前的類屬性字段树姨,修改成ModelSerializer類)
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        # 需要序列化的model類
        model = User

        # 序列化所有的字段
        # fields = '__all__'

        # 序列化指定字段
        # fields = ('name', 'password', 'email', 'sex')

        # 排除哪些字段不進行序列化
        exclude = ('email',)

注意:由于對應了model類的字段,會存在必填字段桥状,所以fileds=__all__exclude慎重使用

  • 進入shell查看ModelSerializer類自動創(chuàng)建了哪些字段和驗證器(fileds=__all__的)

    進入shell

  • 測試是否能添加成功:


    添加成功
2.1帽揪、明確指定字段

當覺得全自動的字段不滿足需求時,可以通過在ModelSerializer類上顯式聲明字段辅斟,從而增加額外的字段或者重寫默認的字段转晰,就和在Serializer類一樣的。
比如:

class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='創(chuàng)建時間', help_text='創(chuàng)建時間', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
明確指定ctime
2.2士飒、指定只讀字段

當我們希望批量將某些字段指定為只讀查邢,而不是顯式的逐一為每個字段添加read_only=True屬性,這種情況就可以使用Metaread_only_fields選項酵幕。
該選項的值是字段名稱所組成的列表或元組扰藕,并像下面這樣聲明:

class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='創(chuàng)建時間', help_text='創(chuàng)建時間', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
        read_only_fields = ('sex', 'password')
批量指定只讀

注意: 有一種特殊情況,其中一個只讀字段是模型級別unique_together約束的一部分芳撒。在這種情況下邓深,序列化器需要該字段的值才能驗證約束,但也是不能由用戶編輯的笔刹。
處理此問題的正確方法是在序列化器上顯式指定該字段芥备,同時提供read_only=True和default=…關鍵字參數(shù)。
這種情況的一個例子就是對于一個和其他標識符unique_together的當前認證的User是只讀的舌菜。 在這種情況下可以像下面這樣聲明user字段:

user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
  • PrimaryKeyRelatedField處理反向關聯(lián)關系/反向序列化
    比如說interfaces是projects的從表萌壳。此時的設計是:在創(chuàng)建interface時,前端會傳遞一個project_id,我們實際在創(chuàng)建interface時袱瓮,是不會使用project_id缤骨,project_idinterfaces.modelprojects.model是一個反向關聯(lián)關系。所以我們此時需要為它添加一個顯示字段尺借。
    interfaces/serialzers.py
from rest_framework import serializers

from projects.models import Projects
from interfaces.models import Interfaces


class InterfaceModelSerializer(serializers.ModelSerializer):
    # 從表指定輸出主表外鍵輸出的值
    project = serializers.StringRelatedField(label='所屬項目', read_only=True)
    # 新增model不存在的字段绊起,前端傳遞的是project_id,并且和project表是一個反向關聯(lián)關系褐望,所以需要添加一個顯示字段
    project_id = serializers.PrimaryKeyRelatedField(queryset=Projects.objects.all(), write_only=True,
                                                    label='所屬項目id', help_text='所屬項目id')

    class Meta:
        model = Interfaces
        fields = ('id', 'name', 'tester', 'create_time', 'desc', 'project', 'project_id')

        extra_kwargs = {
            'create_time': {
                'read_only': True
            }
        }

    def create(self, validated_data):
        """
        前端傳的是project_id勒庄,而對應的字段應該是project,所以需要處理下這里
        :param validated_data:
        :return:
        """
        project_id = validated_data.pop('project_id')
        validated_data['project'] = project_id
        interface_obj = super().create(validated_data)
        return interface_obj
2.3瘫里、添加關鍵字參數(shù)

可以通過使用extra_kwargs選項快捷地在字段上指定任意附加的關鍵字參數(shù)实蔽。這個選項是一個將具體字段名稱當作鍵值的字典。

  • 用法:在給字段添加ModelSerializer無法自動添加的額外條件時使用
  • 注意:extra_kwargs的值是一個字段谨读,里面的key需要和校驗參數(shù)一致局装,否則出錯(可看源碼)
    例如:
class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='創(chuàng)建時間', help_text='創(chuàng)建時間', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {
            # model的任意字段
            "name": {
                "write_only": True,  # 字段名別寫錯
                "error_messages": {  #  字段名別寫錯
                    "max_length": "用戶名最多不能超過50個字符"
                }
            }
        }
添加關鍵字參數(shù)
2.4、添加序列化器自定義的校驗
  • 直接復制粘貼過來劳殖,但是要注意铐尚,必須和class Meta平級
class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='創(chuàng)建時間', help_text='創(chuàng)建時間', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {
            # model的任意字段
            "name": {
                "write_only": True,  # 字段名別寫錯
                "error_messages": {  #  字段名別寫錯
                    "max_length": "用戶名最多不能超過50個字符"
                }
            }
        }

    # 自定義字段級別的驗證
    def validate_name(self, value):
        """
        用戶名需要以“用戶”開頭
        :return:
        """
        if not str(value).startswith('用戶'):
            # 拋出erializers.ValidationError異常
            raise serializers.ValidationError(detail='用戶名需要以用戶兩個字開頭')
        # 返回一個驗證過的數(shù)據(jù)
        else:
            return attrs

    # 自定義多個字段的組合驗證規(guī)則
    def validate(self, attrs):
        """
        password和email必需含有“l(fā)zl”這三個字母
        :return:
        """
        if "lzl" not in attrs['password'] or "lzl" not in attrs['email']:
            raise serializers.ValidationError(detail='password和email必需含有“l(fā)zl”這三個字母')
        else:
            return attrs
2.5、views.py的修改
  • ModelSerializer類因為實現(xiàn)了簡單的.create()方法和.update()方法哆姻。所以之前的views.py中的代碼只需要把之前的Serializer類改成調(diào)用繼承了ModelSerializer的類即可
2.6宣增、指定外鍵序列化輸出的值(從表指定主表外鍵)

主表:projcet
從表:interface
在interface副表中,外鍵是projcet
當使用ModelSerializer進行序列化時矛缨,默認會對project外鍵進行處理爹脾,默認生成的是PrimaryKeyRelatedField序列化器字段,序列化輸出的是該interface對應的project表的id箕昭。
如果需要修改灵妨,那么需要顯示處理:

from rest_framework import serializers

from interfaces.models import Interfaces
from projects.serializer import ProjectModelSerializer

class InterfaceModelSerializer(serializers.ModelSerializer):
    # 指定外鍵序列化輸出內(nèi)容(project是interface的外鍵字段)
    # 1、StringRelatedField:此字段會被序列化為關聯(lián)對象字符串表達形式落竹,也就是__str__方法的內(nèi)容
    project = serializers.StringRelatedField(label='所屬項目')
    # 2泌霍、SlugRelatedField:指定序列化返回的字段,比如下面序列化的結果是關聯(lián)project表的leader字段的值
    project = serializers.SlugRelatedField(label='所屬項目',  slug_field='leader')
    # 3述召、  指定返回關聯(lián)的project序列化器(需要指定read_only朱转,不然前端就需要輸入一個project序列化器)
    project = ProjectModelSerializer((label='所屬項目',  read_only=True)

    class Meta:
        model = Interfaces
        fields = '__all__'
2.6、指定外鍵序列化輸出的值(主表指定從表)

主表中不會默認生成從表的關聯(lián)字段桨武,需要手動指定肋拔,并且字段名是從表名_set。其它方法和和在從表指定主表的一樣呀酸。

class ProjectModelSerializer(serializers.ModelSerializer):
    #注意字段名,并且由于是從表琼梆,多的一方性誉,要指定many=True
    interfaces_set = serializers.StringRelatedField(label='項目接口', many=True)
    class Meta:
        model = Interfaces
        fields = '__all__'
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窿吩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子错览,更是在濱河造成了極大的恐慌纫雁,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倾哺,死亡現(xiàn)場離奇詭異轧邪,居然都是意外死亡,警方通過查閱死者的電腦和手機羞海,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門忌愚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人却邓,你說我怎么就攤上這事硕糊。” “怎么了腊徙?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵简十,是天一觀的道長。 經(jīng)常有香客問我撬腾,道長螟蝙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任民傻,我火速辦了婚禮胰默,結果婚禮上,老公的妹妹穿的比我還像新娘饰潜。我一直安慰自己初坠,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布彭雾。 她就那樣靜靜地躺著碟刺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪薯酝。 梳的紋絲不亂的頭發(fā)上半沽,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音吴菠,去河邊找鬼者填。 笑死,一個胖子當著我的面吹牛做葵,可吹牛的內(nèi)容都是我干的占哟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼榨乎!你這毒婦竟也來了怎燥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蜜暑,失蹤者是張志新(化名)和其女友劉穎铐姚,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肛捍,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡隐绵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拙毫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片依许。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖恬偷,靈堂內(nèi)的尸體忽然破棺而出悍手,到底是詐尸還是另有隱情,我是刑警寧澤袍患,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布坦康,位于F島的核電站,受9級特大地震影響诡延,放射性物質(zhì)發(fā)生泄漏滞欠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一肆良、第九天 我趴在偏房一處隱蔽的房頂上張望筛璧。 院中可真熱鬧,春花似錦惹恃、人聲如沸夭谤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朗儒。三九已至,卻和暖如春参淹,著一層夾襖步出監(jiān)牢的瞬間醉锄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工浙值, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留恳不,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓开呐,卻偏偏與公主長得像烟勋,于是被迫代替她去往敵國和親规求。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355