可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I need to take a form that has a field "starttime" that is in EPOCH and convert it to
- python datetime
- 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.
回答1:
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')
回答2:
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))
回答3:
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.
回答4:
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)
回答5:
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()))