Django rest framework updating time using EPOCH ti

2019-04-09 02:05发布

I need to take a form that has a field "starttime" that is in EPOCH and convert it to

  1. python datetime
  2. fieldname = "created"

when I have:

models.py

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

    class Meta:
        ordering = ('created',)

serializers.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')

If I:

"GET" /snippets/1/

{"id":1, 'starttime':13232111}

I want to be able to do:

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

{"id":1, 'starttime':1}

right now, it just ignores the request. I am forced to use unix epoch times to conform to existing API's.

5条回答
迷人小祖宗
2楼-- · 2019-04-09 02:42

If I understand it correctly, you need to deserialize the starttime field and use it's value to update created field. If that's so, then you need to create your own serializer field and override field_from_native (it doesn't return anything by default, that's why it doesn't have any effect in your case):

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)

so the idea is simple, just reverse the calculation to generate created value and use your new serializer field. You can also move the content from the epoch method into field_to_native method of the new serializer field.

查看更多
Evening l夕情丶
3楼-- · 2019-04-09 02:50

Based on Kevin Stone's answer, I've created timezone aware serializer fields, including a UnixEpochDateField. The actual conversion methods are static because I've found them useful elsewhere in my code.

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)
查看更多
再贱就再见
4楼-- · 2019-04-09 02:57

Please see below code it will help you to solve your problem.

class UnixEpochDateField(serializers.DateField):
    def to_representation(self, value):
        return int(time.mktime(value.timetuple()))
查看更多
男人必须洒脱
5楼-- · 2019-04-09 03:02

Adapting Kevin Stone code for Django Rest Framework 3:

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))
查看更多
虎瘦雄心在
6楼-- · 2019-04-09 03:03

You want to write your own serializer Field sub-class with overridden to_native() and from_native() for the actual conversion. Here's my attempt:

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))

And then use that field in your Serializer definition:

class SnippetSerializer(serializers.ModelSerializer):
    starttime  = UnixEpochDateField(source='created')
查看更多
登录 后发表回答