6

我需要采用在 EPOCH 中具有“开始时间”字段的表单并将其转换为

  1. 蟒蛇日期时间
  2. 字段名 = “创建”

当我有:

模型.py

class Snippet(models.Model):
    created = models.DateTimeField(auto_now_add=True

    class Meta:
        ordering = ('created',)

序列化程序.py

import time
class SnippetSerializer(serializers.ModelSerializer):
    starttime  = serializers.SerializerMethodField('epoch')

    def epoch(self, obj):
        """ Return epoch time for a datetime object or ``None``"""
        try:
            return int(time.mktime(obj.created.timetuple()))
        except (AttributeError, TypeError):
            return None

    class Meta:
        model = Snippet
        fields = ('starttime')

如果我:

“获取”/snippets/1/

{“id”:1,“开始时间”:13232111}

我希望能够做到:

"POST" /snippets/1/ {"id":1, 'starttime':1}

{“id”:1,“开始时间”:1}

现在,它只是忽略了请求。我被迫使用 unix 纪元时间来符合现有的 API。

4

5 回答 5

20

您想编写自己的序列化器 Field 子类并重写to_native()from_native()用于实际转换。这是我的尝试:

class UnixEpochDateField(serializers.DateTimeField):
    def to_native(self, value):
        """ Return epoch time for a datetime object or ``None``"""
        import time
        try:
            return int(time.mktime(value.timetuple()))
        except (AttributeError, TypeError):
            return None

    def from_native(self, value):
        import datetime
        return datetime.datetime.fromtimestamp(int(value))

Serializer然后在您的定义中使用该字段:

class SnippetSerializer(serializers.ModelSerializer):
    starttime  = UnixEpochDateField(source='created')
于 2013-10-15T09:38:33.297 回答
16

为 Django Rest Framework 3 改编 Kevin Stone 代码:

class UnixEpochDateField(serializers.DateTimeField):
    def to_representation(self, value):
        """ Return epoch time for a datetime object or ``None``"""
        import time
        try:
            return int(time.mktime(value.timetuple()))
        except (AttributeError, TypeError):
            return None

    def to_internal_value(self, value):
        import datetime
        return datetime.datetime.fromtimestamp(int(value))
于 2015-02-26T11:11:20.803 回答
0

根据Kevin Stone 的回答,我创建了时区感知序列化器字段,包括UnixEpochDateField. 实际的转换方法是静态的,因为我发现它们在我的代码的其他地方很有用。

class UnixEpochDateTimeField(DateTimeField):
    def to_native(self, value):
        """
        to_native method is responsible for turning the 
        Python object into a simple, serializable value.
        Here: return epoch time for a datetime object or `None`
        """
        return self.datetime_to_epoch(value)

    def from_native(self, value):
            return self.epoch_to_datetime(value)

    @staticmethod
    def datetime_to_epoch(value):
        try:
            return int(calendar.timegm(value.utctimetuple()))
        except (AttributeError, TypeError):
            return None

    @staticmethod
    def epoch_to_datetime(value):
        try:
            return datetime.datetime.utcfromtimestamp(int(value)).replace(tzinfo=utc)
        except (ValueError, TypeError):
            raise ValidationError('%s is not a valid value' % value)


class UnixEpochDateField(DateField):
    def to_native(self, value):
        return self.date_to_epoch(value)

    def from_native(self, value):
            return self.epoch_to_date(value)

    @staticmethod
    def date_to_epoch(value):
        try:
            return int(calendar.timegm(value.timetuple()))
        except (AttributeError, TypeError):
            return None

    @staticmethod
    def epoch_to_date(value):
        try:
            return datetime.date.fromtimestamp(int(value))
        except (ValueError, TypeError):
            raise ValidationError('%s is not a valid value' % value)
于 2014-08-17T16:49:57.940 回答
0

如果我理解正确,您需要反序列化该starttime字段并使用它的值来更新created字段。如果是这样,那么您需要创建自己的序列化器字段并覆盖field_from_native(默认情况下它不返回任何内容,这就是为什么它对您的情况没有任何影响):

class EpochSerializerField(SerializerMethodField):
    def field_from_native(self, data, files, field_name, into):
        starttime = data['starttime']
        # generate `created` value using `starttime`

        into['created'] = created
        super(EpochSerializerField, self).field_from_native(data, files, field_name, into)

所以这个想法很简单,只需反转计算以生成created值并使用新的序列化器字段。您还可以将内容从 epoch 方法移动到field_to_native新序列化器字段的方法中。

于 2013-10-15T09:29:11.593 回答
0

请参阅下面的代码,它将帮助您解决问题。

class UnixEpochDateField(serializers.DateField):
    def to_representation(self, value):
        return int(time.mktime(value.timetuple()))
于 2018-11-12T16:48:09.627 回答