Django-rest-framework: 2つのわずかに異なるiso8601日時シリアル化

作成日 2016年07月11日  ·  3コメント  ·  ソース: encode/django-rest-framework

チェックリスト

  • [x]その問題がDjangoRESTフレームワークのmasterブランチに対して存在することを確認しました。
  • [x]オープンチケットとクローズドチケットの両方で同様の問題を検索しましたが、重複が見つかりません。
  • [x]これは使用上の問題ではありません。 (代わりに、ディスカッショングループに転送する必要があります。)
  • [x]これはサードパーティのライブラリとして扱うことはできません。 (可能な場合は、新しい機能ををお勧めします。)
  • [x]問題を可能な限り単純なケースに減らしました。
  • []プルリクエストとして失敗したテストを含めました。 (それができない場合でも、問題を受け入れることができます。)

    再現する手順

ISO-8601形式での日時シリアル化の実装は、コードベースで一貫していません。
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py#L1094では、マイクロ秒がシリアル化された値に含まれています
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/utils/encoders.py#L30ではミリ秒のみです

予想される行動

一貫した実装を期待します。

実際の動作

該当なし

Bug

最も参考になるコメント

@georgejleeこれを

import datetime

from rest_framework.renderers import JSONRenderer
from rest_framework.utils.encoders import JSONEncoder

class MilliSecondEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            representation = obj.isoformat()
            if obj.microsecond:
                representation = representation[:23] + representation[26:]
            if representation.endswith('+00:00'):
                representation = representation[:-6] + 'Z'
            return representation
        else:
            return super().default(obj)


class JSONRenderer(JSONRenderer):
    encoder_class = MilliSecondEncoder

うーん、DEFAULT_RENDERER_CLASSESをカスタムレンダラーに変更しても、ビューセットのレンダリングには影響しませんでした。 奇妙なことに、renderer_classを明示的に設定する必要がありました。

全てのコメント3件

現在、私のAPIの一部のクライアントは、ミリ秒の精度の日付を必要とし、マイクロ秒を処理できません。 これは、DRF3.3の設定で「DATETIME_FORMAT」を「なし」に設定することで実現しました。 3.4にアップグレードすると、この動作が中断されます。 以前の動作を取得する簡単な方法はありますか? ECMA-262形式を提供する日時形式の文字列を指定する方法がわかりません。 ありがとう。

@georgejleeこれを

import datetime

from rest_framework.renderers import JSONRenderer
from rest_framework.utils.encoders import JSONEncoder

class MilliSecondEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            representation = obj.isoformat()
            if obj.microsecond:
                representation = representation[:23] + representation[26:]
            if representation.endswith('+00:00'):
                representation = representation[:-6] + 'Z'
            return representation
        else:
            return super().default(obj)


class JSONRenderer(JSONRenderer):
    encoder_class = MilliSecondEncoder

うーん、DEFAULT_RENDERER_CLASSESをカスタムレンダラーに変更しても、ビューセットのレンダリングには影響しませんでした。 奇妙なことに、renderer_classを明示的に設定する必要がありました。

encoder_classに対してdatetime encoder_classを介してカスタムエンコーダーを使用するようにDRFを構成しようとしているときに、他の誰かがこれに遭遇した場合。 https://github.com/encode/django-rest-framework/issues/4255#issuecomment -234560555のソリューションが機能しなくなった問題は、フィールドのDateTimeFieldのいずれかでない限り、DRFが組み込みのエンコーダーを使用することformatにkwargセットをNoneを指定しない場合、またはDateTimeFieldシリアライザを、あなたは設定する必要がありますREST_FRAMEWORKの設定以下のためのDEFAULT_FORMAT: Noneあなたの中にsettings.py 。 その場合にのみ、 custom encoderが使用されます。

その理由は、カスタムRendererを使用してdatetimeをレンダリングする前に、シリアライザーフィールド(またはデフォルトのフィールドレンダラー)を使用してResponseをフォーマットするためです。 したがって、datetimeフィールドはすでに文字列になっており、デフォルトのPythonタイプはエンコーダーによって処理されるため、デフォルトのJSONEncoderはカスタムエンコーダーを呼び出さないため、カスタムエンコーダーのdefaultメソッドは呼び出されません。

このページは役に立ちましたか?
0 / 5 - 0 評価