讀寫模型中的選項字段

GET API 返回選項的字符串而不是ID

Django 中常常要用到選項字段

只讀顯示字符串

為了提高數(shù)據(jù)庫效率和用戶可讀性,我們實際存儲的是整數(shù),顯示的時候以字符串顯示。
這個屬性在 Django Admin 得到了很好的處理,但到了 Django Rest Framework 就不會自動轉(zhuǎn)化了墙懂。
下面的在GET的時候顯示字符串,但這個字段就變成只讀但了扮念。

# models.py
class User(AbstractUser):
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )

    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)


# serializers.py 
class UserSerializer(serializers.ModelSerializer):
    # 自定義了gender 字段损搬,該字段變成只讀的了。
    gender = serializers.CharField(source='get_gender_display')

    class Meta:
        model = User


# viewsets.py
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

這里涉及到一個有趣的實例方法: get_FOO_display
對于模型中含有 ++choices++ 參數(shù)的字段柜与, FOO 是字段的名字巧勤, get_FOO_display() 返回選項的可讀字符串

【重點】可讀寫:GET-顯示選項名字 POST-接受數(shù)字

要實現(xiàn) model 中的 Choice Field, 在 GET 的時候顯示選項名字弄匕,在POST的時候既能字符串又能接受ID

接受下面singo評論的建議:參考 stackoverflow 最佳方法如下:

class CommonInfoSerializer(serializers.ModelSerializer):
    ....
    def to_representation(self, instance):
        data = super().to_representation(instance)
        # 返回 data 是一個字典颅悉,更新里面的 status 值
        data.update(status=instance.get_status_display())
        return data

get_<field_name>_display() 是一個自帶的方法,返回選項字段的可讀值(字符串)

完美解決 ??


以下其他方法在更復雜的情況下才考慮迁匠,可以忽略

方法一

比如模型中有個status

# models.py
class CommonInfo(models.Model):
    INACTIVE = 0
    PUBLISHED = 1
    PENDING = -1
    DRAFT = -2
    REPORTED = -3
    DELETED = -4
    STATUS_CHOICES = (
        (INACTIVE, 'INACTIVE'),
        (PUBLISHED, 'PUBLISHED'),
        (PENDING, 'PENDING'),
        (DRAFT, 'DRAFT'),
        (REPORTED, 'REPORTED'),
        (DELETED, 'DELETED'),
    )
    status = models.SmallIntegerField(
            choices=STATUS_CHOICES, default=PUBLISHED)
# utils.py
from rest_framework import serializers
from collections import OrderedDict


class ChoiceDisplayField(serializers.Field):
    """Custom ChoiceField serializer field."""

    def __init__(self, choices, **kwargs):
        """init."""
        self._choices = OrderedDict(choices)
        super(ChoiceDisplayField, self).__init__(**kwargs)

    # 返回可讀性良好的字符串而不是 1剩瓶,-1 這樣的數(shù)字
    def to_representation(self, obj):
        """Used while retrieving value for the field."""
        return self._choices[obj]

    def to_internal_value(self, data):
        """Used while storing value for the field."""
        for i in self._choices:
            # 這樣無論用戶POST上來但是CHOICES的 Key 還是Value 都能被接受
            if i == data or self._choices[i] == data:
                return i
        raise serializers.ValidationError("Acceptable values are {0}.".format(list(self._choices.values())))

# serializers.py
from utils import ChoiceDisplayField
class CommonInfoSerializer(serializers.ModelSerializer):
    INACTIVE = 0
    PUBLISHED = 1
    PENDING = -1
    DRAFT = -2
    REPORTED = -3
    DELETED = -4
    STATUS_CHOICES = (
        (INACTIVE, 'INACTIVE'),
        (PUBLISHED, 'PUBLISHED'),
        (PENDING, 'PENDING'),
        (DRAFT, 'DRAFT'),
        (REPORTED, 'REPORTED'),
        (DELETED, 'DELETED'),
    )
    status = ChoiceDisplayField(choices=STATUS_CHOICES)

方法二

  • 參考頁面提到了更簡單的方法,雖然我沒有試過城丧。
  • 即:繼承 ChoiceField 而不是 Field延曙,就樣就不用寫 to_internal_value() 了。
  • 但 POST 只能接受 ID亡哄, 不能接受字符串枝缔,如下
from rest_framework import serializers
from collections import OrderedDict


class ChoiceDisplayField(serializers.ChoiceField):
    """Custom ChoiceField serializer field."""

    def __init__(self, choices, **kwargs):
        """init."""
        self._choices = OrderedDict(choices)
        super(ChoiceDisplayField, self).__init__(**kwargs)

    # 返回可讀性良好的字符串而不是 1,-1 這樣的數(shù)字
    def to_representation(self, obj):
        """Used while retrieving value for the field."""
        return self._choices[obj]

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚊惯,一起剝皮案震驚了整個濱河市愿卸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌截型,老刑警劉巖趴荸,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異菠劝,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門赶诊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笼平,“玉大人,你說我怎么就攤上這事舔痪≡⒌鳎” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵锄码,是天一觀的道長夺英。 經(jīng)常有香客問我,道長滋捶,這世上最難降的妖魔是什么痛悯? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮重窟,結(jié)果婚禮上载萌,老公的妹妹穿的比我還像新娘。我一直安慰自己巡扇,他們只是感情好扭仁,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厅翔,像睡著了一般乖坠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刀闷,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天熊泵,我揣著相機與錄音,去河邊找鬼涩赢。 笑死戈次,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的筒扒。 我是一名探鬼主播怯邪,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼花墩!你這毒婦竟也來了悬秉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤冰蘑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后祠肥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體武氓,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了县恕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片东羹。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖忠烛,靈堂內(nèi)的尸體忽然破棺而出属提,到底是詐尸還是另有隱情,我是刑警寧澤美尸,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布冤议,位于F島的核電站,受9級特大地震影響师坎,放射性物質(zhì)發(fā)生泄漏恕酸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一屹耐、第九天 我趴在偏房一處隱蔽的房頂上張望尸疆。 院中可真熱鬧,春花似錦惶岭、人聲如沸寿弱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽症革。三九已至,卻和暖如春鸯旁,著一層夾襖步出監(jiān)牢的瞬間噪矛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工铺罢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艇挨,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓韭赘,卻偏偏與公主長得像缩滨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泉瞻,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 關于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,930評論 2 89
  • 模型是關于您的數(shù)據(jù)的單一的脉漏、確定的信息來源。它包含您存儲的數(shù)據(jù)的基本字段和行為袖牙。通常侧巨,每個模型映射到單個數(shù)據(jù)庫表。...
    Mlotjve閱讀 33,879評論 3 16
  • Django 準備 “虛擬環(huán)境為什么需要虛擬環(huán)境:到目前位置鞭达,我們所有的第三方包安裝都是直接通過 pip inst...
    33jubi閱讀 1,326評論 0 5
  • 原文:https://my.oschina.net/liuyuantao/blog/751438 查詢集API 參...
    陽光小鎮(zhèn)少爺閱讀 3,823評論 0 8
  • 背起行囊闖天下 陌生城市把根扎 抬頭望月補元氣 低頭看路再努力
    吾am浪子閱讀 409評論 0 0