Django-rest-framework: Duas serializações iso 8601 datetime ligeiramente diferentes

Criado em 11 jul. 2016  ·  3Comentários  ·  Fonte: encode/django-rest-framework

Lista de controle

  • [x] Eu verifiquei que esse problema existe no branch master da estrutura REST do Django.
  • [x] Pesquisei problemas semelhantes em tíquetes abertos e fechados e não consigo encontrar uma duplicata.
  • [x] Esta não é uma questão de uso. (Em vez disso, eles devem ser direcionados ao grupo de discussão .)
  • [x] Isso não pode ser tratado como uma biblioteca de terceiros. (Preferimos que a nova funcionalidade esteja na forma de bibliotecas de terceiros, sempre que possível.)
  • [x] Reduzi o problema ao caso mais simples possível.
  • [] Incluí um teste de falha como uma solicitação de pull. (Se você não puder fazer isso, ainda podemos aceitar o problema.)

    Passos para reproduzir

A implementação da serialização de data e hora no formato ISO-8601 não é consistente na base de código.
Em https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py#L1094 microssegundos são incluídos no valor serializado
Em https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/utils/encoders.py#L30 apenas milissegundos são

Comportamento esperado

Eu esperaria uma implementação consistente.

Comportamento real

N / D

Bug

Comentários muito úteis

@georgejlee Eu uso um renderizador personalizado para contornar isso:

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

Hmm, alterar DEFAULT_RENDERER_CLASSES para renderizador personalizado não afetou a renderização de meus conjuntos de visualizações. Tive que definir renderer_class explicitamente, estranho.

Todos 3 comentários

Atualmente, alguns clientes da minha API exigem datas com precisão de milissegundos e não podem lidar com microssegundos. Consegui isso definindo 'DATETIME_FORMAT' como Nenhum nas configurações do DRF 3.3. Atualizar para 3.4 quebra esse comportamento. Existe uma maneira fácil de obter o comportamento anterior? Não consigo descobrir como especificar uma string de formato de data e hora que me forneça o formato ECMA-262. Obrigado.

@georgejlee Eu uso um renderizador personalizado para contornar isso:

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

Hmm, alterar DEFAULT_RENDERER_CLASSES para renderizador personalizado não afetou a renderização de meus conjuntos de visualizações. Tive que definir renderer_class explicitamente, estranho.

Caso alguém se depare com isso ao tentar configurar o DRF para usar um codificador personalizado via encoder_class para datetime . O problema que impediu a solução em https://github.com/encode/django-rest-framework/issues/4255#issuecomment -234560555 de funcionar para mim foi que o DRF usará seu codificador integrado, a menos que o DateTimeField tem seu format kwarg definido como None OU, se você não especificar DateTimeField serializadores, então você precisa definir a configuração de REST_FRAMEWORK por DEFAULT_FORMAT: None em seu settings.py . Só então custom encoder será usado.

O motivo é que o (s) campo (s) do serializador (ou renderizador de campo padrão) serão usados ​​para formatar o Response antes que o Renderer seja usado para renderizar o datetime . Portanto, o campo datetime já será uma string e o JSONEncoder padrão não invocará o codificador personalizado, uma vez que os tipos Python padrão são tratados pelo codificador, então o método default do codificador personalizado não será chamado.

Esta página foi útil?
0 / 5 - 0 avaliações