亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 Django REST Framework 中使用默認日期時間序列化?

如何在 Django REST Framework 中使用默認日期時間序列化?

鴻蒙傳說 2021-11-09 15:42:50
我有一個包含以下內容的 Django REST Framework 序列化程序:from rest_framework import serializersclass ThingSerializer(serializers.ModelSerializer):    last_changed = serializers.SerializerMethodField(read_only=True)    def get_last_changed(self, instance: Thing) -> str:        log_entry = LogEntry.objects.get_for_object(instance).latest()        representation: str = serializers.DateTimeField('%Y-%m-%dT%H:%M:%SZ').to_representation(log_entry.timestamp)        return representation這是有問題的,因為如果日期時間格式發生變化,它將與所有其他datetimes 不同。我想重用 DRF 用于序列化其他datetime字段的代碼路徑。到目前為止我嘗試過的:唯一看起來相關的答案實際上并沒有產生與 DRF 相同的結果(它包括毫秒,而 DRF 沒有),大概是因為它使用的是 Django 而不是 DRF 序列化器。rest_framework.serializers.DateTimeField().to_representation(log_entry.timestamp),rest_framework.fields.DateTimeField().to_representation(log_entry.timestamp)并rest_framework.fields.DateTimeField(format=api_settings.DATETIME_FORMAT).to_representation(log_entry.timestamp)沒有任何工作; 它們以微秒精度生成字符串。我已經用調試器驗證了 DRF 在序列化其他字段時調用后者,所以我不明白為什么它會在我的情況下產生不同的結果。LogEntry.timestamp被聲明為 a django.db.DateTimeField,但如果我嘗試類似的事情,LogEntry.timestamp.to_representation(log_entry.timestamp)它會失敗:AttributeError: 'DeferredAttribute' 對象沒有屬性 'to_representation'
查看完整描述

1 回答

?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

查看 DRF 的來源,有趣的事情發生在rest_framework/fields.py.


特別是,所有格式化的東西都直接在DateTimeField.to_representation方法中發生。


您有幾種復制 DRF 行為的方法。


首先,您根本無法傳遞格式。如果您未明確提供格式,DRF 應使用其默認值。


representation: str = serializers.DateTimeField().to_representation(log_entry.timestamp)

或者,繼續做你正在做的事情,但從 DRF 的api_settings.DATETIME_FORMAT. 這可能感覺不那么神奇,但老實說,未來的 API 更改可能會更加脆弱。


這可能看起來像:


from rest_framework.settings import api_settings

...

representation: str = serializers.DateTimeField(api_settings.DATETIME_FORMAT).to_representation(log_entry.timestamp)

但是,鑒于您嘗試了第一個并且失敗了,我們需要更深入地研究!


DRF 的默認 DateFormat 是ISO_8601,其中包含以下代碼:


value = value.isoformat()

if value.endswith('+00:00'):

    value = value[:-6] + 'Z'

    return value

也就是說,它實際上只是依賴于 pythonisoformat函數。


isoformat如果該值有微秒,則格式會有所不同。


從Python 文檔中,isoformat將:


以 ISO 8601 格式返回表示日期和時間的字符串,YYYY-MM-DDTHH:MM:SS.ffffff 或者,如果微秒為 0,則 YYYY-MM-DDTHH:MM:SS


在這種情況下,解決方案是將時間戳中的微秒顯式設置為零。有幾種方法可以做到這一點,但我們可以切換到 Unix 時間戳,剪輯到秒,然后再回來


ts = int(log_entry.timestamp)

representation: str = serializers.DateTimeField().to_representation(ts)

或者繼續直接使用 DateTime 對象,這將有更好的時區處理:


representation: str = serializers.DateTimeField().to_representation(

        logentry.replace(microsecond=0)

    )


查看完整回答
反對 回復 2021-11-09
  • 1 回答
  • 0 關注
  • 310 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號