èšå®ã«TIME_ZONE = 'Asia/Kolkata'
ãšUSE_TZ = True
ããããŸãã
é²èŠ§å¯èœãªAPIã䜿çšããŠæ°ãããªããžã§ã¯ããäœæãããšãã·ãªã¢ã©ã€ã¶ãŒã¯ãæ°ããäœæããããªããžã§ã¯ãããã¿ã€ã ãŸãŒã³ã瀺ã+5:30
æ«å°Ÿãä»ããæ¥æã§è¡šç€ºããŸãã ããŒã¿ããŒã¹ã¯UTCã§æéãä¿åããŠããŸãã
äºæããªãåäœãšããŠããªããžã§ã¯ããåŸã§å床ã·ãªã¢ã«åããããšãæ¥æã¯ãã¹ãŠUTC圢åŒã«ãªããæ«å°Ÿã«Z
ãŸãã çŸåšã®ã¿ã€ã ãŸãŒã³ãšããã©ã«ãã®ã¿ã€ã ãŸãŒã³ã«é¢ããDjangoã®ããã¥ã¡ã³ãã«ãããšãã·ãªã¢ã©ã€ã¶ãŒãæ¥æãçŸåšã®ã¿ã€ã ãŸãŒã³ã«å€æããããšãæåŸ
ããŠããŸããçŸåšã®ã¿ã€ã ãŸãŒã³ã¯ãããã©ã«ãã§TIME_ZONE = 'Asia/Kolkata'
ã«ãã£ãŠèšå®ãããããã©ã«ãã®ã¿ã€ã ãŸãŒã³ã«ãªããŸãã
ç§ã¯äœãã足ããªãã®ã§ããïŒ
ã¹ã¿ãã¯ãªãŒããŒãããŒã«ã€ããŠå°ãããšãããçŸåšã®ã¿ã€ã ãŸãŒã³ã¯ãŠãŒã¶ãŒãæå®ããæ¥æã«ã®ã¿äœ¿çšããããšããçµè«ã«éããŸãããæ¥æã¯æ€èšŒåŸïŒã€ãŸããäœæãŸãã¯æŽæ°åŸïŒãã®ãŸãŸã·ãªã¢ã«åãããããã§ãã Djangoã®ããã¥ã¡ã³ãããããããæå³ãããåäœã§ãããšã¯ä¿¡ããããã§ãããããã¯Rest Frameworkã§ã¯ãªãDjangoèªäœã®åé¡ã§ããããããã®åé¡ãéããŸãã
ããã«ã¡ã¯@tomchristie ã
ããã¯DRFã®ãã°ã ãšæããŸãã
IMHOãDRFã®èªç¶ãªäœ¿çšæ³ã¯ãdjangoãã³ãã¬ãŒãã®ãããªåºåãšããŠäœ¿çšããããšã§ãã
djangoãã³ãã¬ãŒãã§ã¿ã€ã ãŸãŒã³ãæ£ãã衚瀺ãããŠããã®ã«ãdrfã·ãªã¢ã©ã€ã¶ãŒãdjangoã®ã¿ã€ã ãŸãŒã³èšå®ãå°éããªãã®ã¯ãªãã§ããïŒ
ããã
DatetimeField
ã¯ã©ã¹ã®fields.py
ã®ã³ãŒãã調ã¹ããšãDjangoã®ã¿ã€ã ãŸãŒã³èšå®ãå
éšå€ïŒ to_internal_value()
ïŒã«å¯ŸããŠã®ã¿èæ
®ãããŠããããšãããããŸããã
ç§ã¯æ¬¡ã®ãããªã¢ãã«ã·ãªã¢ã©ã€ã¶ãŒã䜿çšããŠããã®ãèŠãŠããŸããïŒ
class MyModelSerializer(ModelSerializer):
class Meta:
model = MyModel
depth = 1
fields = ('some_field', 'my_date_time_field')
ãã£ãŒã«ãmy_date_time_field
ïŒDateTimeFieldã ãšæããŸã:)ïŒã®å Žåãè¡šçŸã®ã¿ã€ã ãŸãŒã³ã¯ããã©ã«ãã§ã¯Noneã§ãïŒ to_representation()
ïŒã
èšãæããã°ãç§ãééã£ãŠããªããã°ãDjangoã¿ã€ã ãŸãŒã³ã¯å€ãã¹ãã¬ãŒãžããã¯ãšã³ãã«æžã蟌ãŸãããšãã«ã®ã¿èæ ®ãããŸãã
IMHO to_representation()
ã®æ»ãå€ã¯æ¬¡ã®ããã«ãªããšæããŸãã
return self.enforce_timezone(value).strftime(output_format)
Django USE_TZ
èšå®ã«ãããšã
ããã«å¯Ÿãããã«ãªã¯ãšã¹ããäœæããŸãã
ãã£ãª
ãŽã¡ã¬ã³ãã£ã
@vpistisçŸåš
TIME_ZONE = 'Asia/Kolkata'
ãèšå®ããåäžã®æ¥æãã£ãŒã«ãappointment
ãæã€ã¢ãã«ã·ãªã¢ã©ã€ã¶ãŒãäœæããŸãã
äœæ/æŽæ°äžã«ã以äžãéä¿¡ããŸãã
{
"appointment": "2016-12-19T10:00:00"
}
ãããŠæ»ã£ãŠãã ããïŒ
{
"appointment": "2016-12-19T10:00:00+5:30"
}
ãã ãããã®ãªããžã§ã¯ããå床ååŸãŸãã¯äžèŠ§è¡šç€ºãããšã次ã®ããã«ãªããŸãã
{
"appointment": "2016-12-19T04:30:00Z"
}
äœææã«Zãæå®ãããŠããªãå ŽåãDRFã¯ãã¯ã©ã€ã¢ã³ããTIME_ZONE
æå®ãããã¿ã€ã ãŸãŒã³ã䜿çšããŠãããšèŠãªãããã®ã¿ã€ã ãŸãŒã³ã«ãã©ãŒããããããæéãè¿ããŸãïŒæåŸã«+5:30
ãè¿œå ããŸããã¯ã©ã€ã¢ã³ããæäŸããæéã§ããã°ãå®éã«ã¯ç¡å¹ã«ãªããŸãïŒã å°æ¥ã®ã¢ã¯ã»ã¹ã§ããã®ã¿ã€ã ãŸãŒã³ã«ãã©ãŒããããããæå»ãè¿ãããå Žåã¯ãããããããçã«ããªã£ãŠãããããååŸ/ãªã¹ãäžã®å¿çã¯äœæ/æŽæ°äžãšåãã§ããã
äœæ/æŽæ°äžã«æ«å°Ÿã®ZãæäŸããããšãã«ãæ§æãããã¿ã€ã ãŸãŒã³ã§æéãè¿ããã©ãããšããåé¡ããããŸããããšãã°ã次ã®ããã«éä¿¡ããŸãã
{
"appointment": "2016-12-19T04:30:00Z"
}
æ»ãå€ïŒ
{
"appointment": "2016-12-19T10:00:00+5:30"
}
ãªã¹ã/ååŸã®å¿çãšäžè²«æ§ã®ããå¿çãç¶æããã®ã§ãç§ã¯ããã«è³æã§ãã
ãã1ã€ã®ãªãã·ã§ã³ã¯ãäœæ/æŽæ°äžã§ãã£ãŠããåžžã«UTCæéãè¿ãããšã§ãããããŸã圹ã«ç«ããªãããšãããããŸããã ãããã«ãããçŸåšã®50/50ã®ãããªç¶æ³ããããäžè²«ããã¿ã€ã ãŸãŒã³ãæã€ããšãæãŸããã§ãããã
TIME_ZONE = 'Asia / Kolkata'ãèšå®ããåäžã®æ¥æãã£ãŒã«ãã§ããäºå®ãæã€ã¢ãã«ã·ãªã¢ã©ã€ã¶ãŒãäœæããŸãã
äœæ/æŽæ°äžã«ã以äžãéä¿¡ããŸãã
{{
ãäºå®ãïŒã2016-12-19T10ïŒ00ïŒ00ã
}
ãããŠæ»ã£ãŠãã ããïŒ{{
"äºå®"ïŒ "2016-12-19T10ïŒ00ïŒ00 + 5ïŒ30"
}
ãã ãããã®ãªããžã§ã¯ããå床ååŸãŸãã¯äžèŠ§è¡šç€ºãããšã次ã®ããã«ãªããŸãã{{
ãäºå®ãïŒã2016-12-19T04ïŒ30ïŒ00Zã
}
ããããšã@ jonathan-golorryããã¯ç§ãå®éã«èŠãŠããæ£ç¢ºãªåäœã§ãã
ç§ã®å Žåãåäœã¯æ¬¡ã®ããã«ãªããŸãïŒ@ jonathan-golorryã®äŸã䜿çš:)ïŒïŒ
ããã©ã«ãã®DATETIME_FORMATã䜿çšããäœæ/æŽæ°äžã«ã以äžãéä¿¡ããŸãã
{
"appointment": "2016-12-19T10:00:00"
}
ãããŠæ»ã£ãŠãã ããïŒ
{
"appointment": "2016-12-19T10:00:00+5:30"
}
ãã®ãªããžã§ã¯ããå床ååŸãŸãã¯äžèŠ§è¡šç€ºãããšã次ã®ããã«ãªããŸãã
{
"appointment": "2016-12-19T10:00:00+5:30"
}
IMHOã¯ããã®åäœã管çããããã®DRFèšå®ã§ããå¿ èŠããããŸããããšãã°ãDateTimeFieldãããã©ã«ãã®ã¿ã€ã ãŸãŒã³ã§è¡šç€ºããããã«åŒ·å¶ããèšå®ã§ãã
ã©ããããããšã@tomchristie
ç°ãªãã¢ã¯ã·ã§ã³éã®äžäžèŽã¯ãããã§åéããããã®ã¯ãªã³ãã£ãŒã§ãã ããã ãšã¯æããããŸããã§ããã ãªãã·ã§ã³ã«ããããšãã§ããŸãããããã©ã«ãã§ã¯UTCã䜿çšããããšãæåŸ ããŠããŸãã
DRF 3.4.6ã䜿çšããæ¬çªWebã¢ããªã®å Žåã次ã®åé¿çã§è§£æ±ºããŸããã
https://github.com/vpistis/django-rest-framework/commit/be62db9080b19998d4de3a1f651a291d691718f6
誰ãã次ã®ãããããå«ããã«ãªã¯ãšã¹ããéä¿¡ãããå ŽåïŒ
ããã¯å€§æè¿ã§ãã
ãã¹ãããã³ãŒããããã€ãäœæããŸããããdrfãã¹ãã±ãŒã¹ã®äœ¿çšæ¹æ³ãããããŸããã å®è¡æã«ã¿ã€ã ãŸãŒã³ããã®ä»ã®èšå®ãå€æŽããããã«djangoèšå®ã管çããæ¹æ³ãããããŸããã
å
·äœçãªäŸãã¬ã€ãããªã³ã¯ããŠãã ããã
ããããšã
ã°ããŒãã«ãã¹ãèšå®ãå€æŽããå Žåã¯ãããã«ãã
ãã¹ãäžã«èšå®ãäžæžãããããšããŠããå Žåã¯ã override_settings
ãã³ã¬ãŒã¿ã䜿çšã§ããŸãã
ãã®æ©èœãããã ããã°å¹žãã§ãã æšæºã®Djangoã®åäœãšåæ§ã«ã USE_TZ
èšå®ãå°éããå€ãå€æããå¿
èŠããããšæããŸãã
ããã§ã®æåã®ã¹ãããã¯ãçŸåšã®ãã¹ãã¹ã€ãŒãã«è¿œå ã§ãã倱æãããã¹ãã±ãŒã¹ãäœæããããšã§ãã
次ã®ã¹ãããã¯ããã®å Žåã®ä¿®æ£ãéå§ããããšã§ã:)
ããã
ç§ã«ãšã£ãŠãããã¯ãã®æ©èœã®ãã¹ãã±ãŒã¹ã§ã
class TestDateTimeFieldTimeZone(TestCase):
"""
Valid and invalid values for `DateTimeField`.
"""
from django.utils import timezone
valid_inputs = {
'2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
'2001-01-01T13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
'2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): datetime.datetime(2001, 1, 1, 13, 00,
tzinfo=timezone.get_default_timezone()),
# Django 1.4 does not support timezone string parsing.
'2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone())
}
invalid_inputs = {}
outputs = {
# This is not simple, for now I suppose TIME_ZONE = "Europe/Rome"
datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()): '2001-01-01T13:00:00+01:00',
datetime.datetime(2001, 1, 1, 13, 00, ): '2001-01-01T13:00:00+01:00',
}
field = serializers.DateTimeField()
ç§ã®ãã©ãŒã¯ã§ã¯ãããã€ãã®ããªãã¯ã䜿çšããŠã3.6.2_tz_fixã®æ£ããã¿ã€ã ãŸãŒã³ã§æéãååŸããŸãã
ç§ã¯ãã®å©ããé¡ã£ãŠããŸã:)
ããã¯éããŠããããã§ãããdrf 3.6.3ãå®è¡ããŠããŠãpostgresããŒã¿ããŒã¹ã«ãã®ã¿ã€ã ã¹ã¿ã³ãã2017-07-1214ïŒ26ïŒ00-06ãããããŸãããpostmanã䜿çšããŠããŒã¿ãååŸãããšããã®ãã¿ã€ã ã¹ã¿ã³ãããååŸãããŸãã ïŒã2017-07-12T20ïŒ26ïŒ00Zãã -06æéè¿œå ãããŠããããã§ãã
ç§ã®djangoèšå®ã§ã¯ãtzlocalã䜿çšããŠã¿ã€ã ãŸãŒã³TIME_ZONE = str(get_localzone())
ãŸãã ãããã£ãŠãã¿ã€ã ãŸãŒã³ã¯èµ·åæã«èšå®ãããŸãã
åºæ¬çãªmodelSerializerã䜿çšããŠããŸã
class SnapshotSerializer(serializers.ModelSerializer):
class Meta:
model = Snapshot
resource_name = 'snapshot'
read_only_fields = ('id',)
fields = ('id', 'timestamp', 'snapshot')
ç§ã¯äœãã足ããªãã®ã§ããïŒ
éããŠããŸããããŸã éããŠããŸã:)
衚瀺ãããŠããèµ€ããéãããã¿ã³ãã¯ãåç
§çšã§ãã
...ãããŠããªãã¯æ£ããã§ããããã°ãã¯ãŸã ããã«ãããŸã;ïŒ
ãã€ã«ã¹ããŒã³ã3.6.3ãã3.6.4ã«å€æŽãããŸããã
ãããããããŸããã ããããšãããããŸããïŒ
2017幎7æ12æ¥ååŸ5æ10åããValentinoPistisã [email protected]
æžããŸããïŒ
éããŠããŸããããŸã éããŠããŸã:)
衚瀺ãããŠããèµ€ããéãããã¿ã³ãã¯ãåç §çšã§ãã
...ãããŠããªãã¯æ£ããã§ããããã°ãã¯ãŸã ããã«ãããŸã;ïŒ
ãã€ã«ã¹ããŒã³ã3.6.3ãã3.6.4ã«å€æŽãããŸãããâ
ããªããã³ã¡ã³ãããã®ã§ããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/encode/django-rest-framework/issues/3732#issuecomment-314923582 ã
ãŸãã¯ã¹ã¬ããããã¥ãŒãããŸã
https://github.com/notifications/unsubscribe-auth/AIMBTcx-6PPbi_SOqeLCjeWV1Rb59-Ohks5sNVJ0gaJpZM4G0aRE
ã
ããã
ãããå ã®è³ªåã«å®å šã«é¢é£ããŠãããã©ããã¯ããããŸãããã httpsïŒ //docs.djangoproject.com/en/1.11/ref/utils/#djangoã®ããã«ãDRFãèšå®ãããŠããã¿ã€ã ãŸãŒã³ã®ãªãŒããŒã©ã€ããå°éããå¿ èŠããã
ãŠãŒã¶ãŒãã¿ã€ã ãŸãŒã³ã«é¢é£ä»ããããŠããã·ã¹ãã ããããAPIã¯ãã€ãŒããªæ¥æãåãåããŸãã ãããã®æ¥æãçŸåšã®ãŠãŒã¶ãŒã®ã¿ã€ã ãŸãŒã³ã«å€æã§ãããšæããŸããã ../rest_framework/fields.py
ãããã©ã«ãã®ã¿ã€ã ãŸãŒã³ïŒã€ãŸããdjangoèšå®ãã¡ã€ã«ã®ã¿ã€ã ãŸãŒã³ïŒãé©çšããŠããããšã«æ°ä»ããŸããã
def enforce_timezone(self, value):
field_timezone = getattr(self, 'timezone', self.default_timezone())
if (field_timezone is not None) and not timezone.is_aware(value):
try:
return timezone.make_aware(value, field_timezone)
[...]
def default_timezone(self):
return timezone.get_default_timezone() if settings.USE_TZ else None
ç§ã®å Žåã®ããã«ãã¢ããªã±ãŒã·ã§ã³ããªãŒããŒã©ã€ããèšå®ããå Žåã«åããŠãããã¯å®éã«timezone.get_current_timezone()
ãèšå®ãšããŠäœ¿çšããå¿
èŠããããŸããïŒ
ããã«ã¡ã¯@RichardForshawã¯å¥ã®åé¡ã®ããã§ããã確ãã«åãçå Žã§ãã
æåŸ ãããåäœãã«ããŒããé©åãªãã¹ãã±ãŒã¹ã®ã»ãããååŸã§ããã°ãããã§PRã確èªããããšã¯ééããªããšæããŸãã
ç§ã®æåã®èãã¯ãããè¶ ããŠããµãŒããŒã®æ§æãããã¿ã€ã ãŸãŒã³ã«äŸåããã®ã§ã¯ãªããã¿ã€ã ãŸãŒã³æ å ±ãAPIã«éä¿¡ããããšã確èªããããšã§ãã ãããè¶ ããŠãç§ã¯ããªããã¯ã©ã€ã¢ã³ãã®æéãããŒã«ã©ã€ãºããæºåãããå¿ èŠããããšæãåŸåããããŸãã
ããããã¯ããããã§å¯ŸåŠãã¹ãççŸããããŸãã ïŒPRãžãããããšèšããŸãããïŒðïŒ
carltongibson / django-filterïŒ750ã¯ããã«é¢é£ããŠããã¯ãã§ãã ç§ã¯ããšããšdjango-filterã®ã¿ã€ã ãŸãŒã³åŠçãDRFã«åºã¥ããŠããã®ã§ã750ã§ã®å€æŽãããã§ç°¡åã«é©çšã§ããŸãã
ç§ã®åå¿è ã«ã¯ç³ãèš³ãããŸããããããã§ã®åé¡ã¯æ£ç¢ºã«ã¯äœã§ããïŒ ç§ã®psqlããŒã¿ããŒã¹ã®ã¿ã€ã ã¹ã¿ã³ãã¯æ£ãããDjangoã¯æ£ããã¿ã€ã ãŸãŒã³ã䜿çšããããã«èšå®ãããŠããŸãã ã¿ã€ã ã¹ã¿ã³ããå€æããªãããã«ããDRFèšå®ã¯ãããŸããïŒ
ããã«ã¡ã¯@ michaelaeliseâããŒã¿ã®äŸïŒäžéšè¿ãïŒãèŠããšïŒ
+5:30
ïŒZ
ããZuluãã®å ŽåïŒãã¯ã©ã€ã¢ã³ããã¿ã€ã ãŸãŒã³å€æãåŠçããããšãåæãšããŠãå®éã®åé¡ãã ïŒããããNo1ãé€ããŠãã¯ã©ã€ã¢ã³ãã®ã¿ã€ã ãŸãŒã³èšå®ããµãŒããŒãšåãã§ãããšèª°ãèšãã®ã§ãããã...ïŒïŒ
ããããããã¯å°ãççŸããŠããŸãã確ãã«2ãš3ã¯åã圢åŒã§ããå¿ èŠããããŸããïŒ ïŒã¯ã©ã€ã¢ã³ãã¯æ£ãããã©ã¡ãããåçã®å€ãšããŠåãå ¥ããŸãããïŒ
ç§ã¯ãããéããåŸåããããŸãã
"2016-12-19T10:00:00+5:30"
ãš"2016-12-19T04:30:00Z"
âããçšåºŠã圌ããã©ã®ããã«æ»ã£ãŠããããæ°ã«ããã®ã¯èª°ã§ããïŒPRãèŠãŠããããã§ãããããã_æªè§£æ±ºã®åé¡_ãšæ¬åœã«èããããã©ããã¯ããããŸããã
ããããã®å·ã®ã¹ã¬ããã®å
ã®æçš¿ã§ããZãããããæå³ããŠããããšã«æ°ã¥ããŠããŸããã§ããã
ã§ã¯ãDRFã¯èªèãããæ¥æãUTCã«å€æããŠãUI /åŒã³åºãå
ã«ãã£ãŠåŠçãããŸããïŒ
ãã®èª¬æãããããšãã
æåŸã«äžã€ã ãã
ç°ãªãã¿ã€ã ãŸãŒã³ã§ããã€ã¹ãããŒãªã³ã°ããŠãããããã2016-12-19T10ïŒ00ïŒ00 + 5ïŒ30ããè¿ãããå Žåã¯ã©ããªããŸããã
ããã¯ãRETURN_DATETIME_WITH_TIMEZONEãã®èšå®ã§ããããïŒ
ãšããžããã€ã¹ã§django / drfã䜿çšããŠããŸãã ãããã£ãŠãæ¿å ¥ããããã¹ãŠã®æ¥æã¯ããšããžããã€ã¹ã®ã¿ã€ã ãŸãŒã³ãæ§æãããŠãããpostgresãã£ãŒã«ãããã®ããã€ã¹ã®æ¥æã«å¯ŸããŠåžžã«æ£ç¢ºã§ããããããã€ãŒãã§ãããã©ããã¯é¢ä¿ãããŸããã
çŸåšã®ã·ããªãªã®ã¯ã©ãŠããµãŒããŒã¯ãåããã€ã¹ã®ã¿ã€ã ãŸãŒã³ãç¥ãå¿ èŠããããŸãããããããäœæ¥ãdjango / drfããã¯ã©ãŠãã¢ããªã«ã·ããããŠåŠçããã ãã§ãã
USE_TZãæ³å®ãããšãDRFã¯ãã§ã«ã¿ã€ã ãŸãŒã³æ å ±ãšãšãã«æ¥æãè¿ããŠããŸãã ã ãããããã¯ããªããããã§å¿ èŠãªããšããã§ã«ãã£ãŠããŸãã
ããã§ã®å¯äžã®åé¡ã¯ãåãDTã1ã€ã®ã¿ã€ã ãŸãŒã³ãŸãã¯å¥ã®ã¿ã€ã ãŸãŒã³ã®ããã«ãã©ãŒããããããŠãããã©ããã§ãã ïŒãããããããã¯ãŸã åãæéã§ããïŒ
@carltongibson
ããã«ã¯è«çãšã©ãŒã¯ãããŸããã
ãããã¯åãæéã§ãïŒã2016-12-19T10ïŒ00ïŒ00 + 5ïŒ30ããšã2016-12-19T04ïŒ30ïŒ00ZãâããçšåºŠã圌ããã©ã®ããã«æ»ã£ãŠããããæ°ã«ããã®ã¯èª°ã§ããïŒ
ç§èŠãããåé¡ã§ãïŒè¿ãããæååïŒ
ç§ã¯Djangoã¿ã€ã ãŸãŒã³èšå®ã䜿çšããŠããããã¹ãŠã®ãã³ãã¬ãŒãã¯äºæ³ã©ããæ£ããæå»"2016-12-19T10:00:00+5:30"
è¿ããŸãããDRFã¯è¿ããŸããã DRFã¯"2016-12-19T04:30:00Z"
è¿ããŸãã
ã¯ã©ã€ã¢ã³ãã«ãããã¯ç§ã®REST APIãæ¶è²»ããŸããããã¯ããžãã¯ããæéå€æãæ¥ææåå解éããããŸããã
èšãæãããšãDRFå¿çããã®æ¥æã¯Djangoãã³ãã¬ãŒãã®ãå¿çããšåãã§ãããšæåŸ
ããŠããŸãããµãŒããŒã¯ã¯ã©ã€ã¢ã³ãã®ãã¹ãŠã®ããŒã¿ãæºåããã¯ã©ã€ã¢ã³ãã¯ããã®ã¿ã衚瀺ããŸãã
ãšã«ããããã®çŽ æŽããããããžã§ã¯ããžã®ããªãã®å¿èããµããŒãããããŠããªãã®çŽ æŽãããä»äºã«æè¬ããŸãïŒ
@vpistisããã§ã®ç§ã®ãã€ã³ãã¯ãè¡šçŸãããæ¥ä»ãæ£ãããšããããšã§ããè¡šçŸã ããæåŸ ãããŠããŸããã ããããã€ãã£ãã®æ¥ä»ã«è§£æãããšããã«ãã©ã®èšèªã§ããããåŠçããŸãããéãã¯ãããŸããã
ãŠãŒã¶ãŒãæ¥ä»æååãæ¥ä»ã«è§£æããããšãæåŸ ããŸãããã¯ã©ã€ã¢ã³ãèšèªã¯çã®æååãæ¶è²»ããã®ã§ã¯ãªãããããæäŸããŸãã
ããªããçã®åŒŠãæ¶è²»ããŠãããªããããªãã®æåŸ ã¯ããã§ã¯æºããããŸããã ïŒãã ããããããªãã§ãã ãããUNIXã¿ã€ã ã¹ã¿ã³ããéä¿¡ããå Žåãæ³åããŠãã ãããããããæªå å·¥ã§äœ¿çšããæ¹æ³ã¯ãããŸãããã¯ã©ã€ã¢ã³ãèšèªã«é¢ä¿ãªããé©åãªDateãªããžã§ã¯ãã«å€æããŠãã ãããïŒ
ããã«ã€ããŠPRããšãããšãã§ããŠæ¬åœã«ããããã§ãã ïŒãŸã éããŠããŸããïŒïŒ
ããããå ±åãããŠããã»ãŒ2幎ãæåã®ã³ã¡ã³ããã9ãæãçµã¡ãŸããïŒããªãã®ã1幎åŸïŒã 誰ãç§ãã¡ã«å€±æãããã¹ãã±ãŒã¹ãäžããŠãããŸããã§ããã ããã¯èª°ã«ãšã£ãŠãããã»ã©éèŠãªããšã§ã¯ãããŸããã ãã®ãããæéãå²ãåœãŠãã®ã¯å°é£ã§ãã
ïŒãã®ãããPRãçºçããå Žåã¯PRãè¡ãããšã«åºã¥ããŠééããåŸåããããŸãïŒ
ã¿ãªãããããã«ã¡ã¯ãããã¯ïŒ5408ã§ä¿®æ£ããå¿ èŠããããŸãã ãã©ã³ããã€ã³ã¹ããŒã«ããŠããã¹ãŠãæåŸ ã©ããã«æ©èœããŠããããšã確èªããæéãããã°ãããã¯çŽ æŽãããããšã§ãã ããããšãïŒ
ãã®åé¡ã¯ã©ãããããããåå°å ¥ããããšæããŸãã
ããã©ã«ãã®TZãUTCãããšãŒããã/ã¢ã ã¹ãã«ãã ã«å€æŽãããšãããã¹ãã®1ã€ã倱æããDRFãããã©ã«ãã®TZãšã¯ç°ãªããã®ã«ã·ãªã¢ã«åãããŠããããšã«æ°ä»ããŸããã
ç·šéïŒåé¡ã¯ãã¹ã/å·¥å Žã®ã»ããã¢ããã«é¢é£ããŠããŸããã
以äžã®ã»ããã¢ããããã¹ãããŸãã
ã¢ãã«
class Something(StampedModelMixin):
MIN_VALUE = 1
MAX_VALUE = 500
id = models.BigAutoField(primary_key=True) # pylint: disable=blacklisted-name
product_id = models.BigIntegerField(db_index=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
percentage = models.IntegerField()
enabled = models.IntegerField()
å·¥å Ž
class SomethingFactory(factory.django.DjangoModelFactory):
""" Base Factory to create records for Something
"""
start_time = factory.Faker('date_time', tzinfo=get_default_timezone())
end_time = factory.Faker('date_time', tzinfo=get_default_timezone())
percentage = factory.Faker('random_int', min=1, max=500)
enabled = factory.Faker('random_element', elements=[0, 1])
class Meta: # pylint: disable=missing-docstring
model = Something
åäœãã¹ã
class TestSomething:
def test__get__empty(self):
# preparation of data
series = SeriesFactory.create(product_id=2)
SomethingFactory.create_batch(3, product_id=1)
# prepare request params
url = reverse('series-somethings', kwargs={'pk': series.pk})
# call the endpoint
response = self.client.get(url)
# asserts
assert response.data == []
def test__get__single(self):
# preparation of data
series = SeriesFactory.create(product_id=1)
old_somethings = SomethingFactory.create_batch(1, product_id=1)
# prepare request params
url = reverse('series-somethings', kwargs={'pk': series.pk})
# call the endpoint
response = self.client.get(url)
# asserts
assert SomethingSerializer(old_somethings, many=True).data == response.data
èŠã
class SomethingElseView(APILogMixin, ModelViewSet):
@action(detail=True, methods=['get'])
def somethings(self, request, pk=None):
""" GET endpoint for Somethings
.. seealso:: :func:`rest_framework.decorators.action`
"""
otherthings = self.get_object()
something_qs = Something.objects.all()
something_qs = something_qs.filter(product_id=otherthings.product_id)
serializer = self.something_serializer_class(something_qs, many=True)
return Response(serializer.data)
ã·ãªã¢ã©ã€ã¶ãŒ
class SomethingSerializer(serializers.ModelSerializer):
class Meta:
model = Something
list_serializer_class = SomethingListSerializer
fields = '__all__'
extra_kwargs = {
'percentage': {'min_value': Something.MIN_VALUE,
'max_value': Something.MAX_VALUE}
}
read_only_fields = ('id',
'ts_activated',
'ts_created',
'ts_updated')
ipdbã®çµæããã¹ããã
ipdb> old_somethings
[{'product_id': 1, 'start_time': datetime.datetime(2011, 7, 13, 1, 10, 33, tzinfo=<DstTzInfo 'Europe/Amsterdam' LMT+0:20:00 STD>), 'end_time': datetime.datetime(2003, 3, 10, 9, 31, tzinfo=<DstTzInfo 'Europe/Amsterdam' LMT+0:20:00 STD>), 'percentage': 103, 'enabled': 0}]
ipdb> response.data
[OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:16:33'), ('ts_updated', '2019-02-27 14:16:33'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])]
ãã¹ãçµæ
E AssertionError: assert [OrderedDict(...nabled', 0)])] == [OrderedDict([...nabled', 0)])]
E At index 0 diff: OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 01:10:33'), ('end_time', '2003-03-10 09:31:00'), ('percentage', 103), ('enabled', 0)]) != OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])
E Full diff:
E - [OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 01:10:33'), ('end_time', '2003-03-10 09:31:00'), ('percentage', 103), ('enabled', 0)])]
E ? ^^^^^^^^^^ ^^^^^^^^^^^
E + [OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])]
E ?
ã¹ã¿ãã¯ïŒ
Django==2.0.10
djangorestframework==3.9.0
factory-boy==2.11.1
Faker==0.8.18
pytz==2018.9
ããã«ã¡ã¯@ diegueus9-ãããããåçŽãªãã¹ãã±ãŒã¹ã«æžããããšãã§ããŸããïŒ ã·ãªã¢ã«åãããåœã®ããŒã¿ãšãã¥ãŒã®å¿çããŒã¿ãæ¯èŒããŠããŸãã ãããã£ãŠãå®éã®æåŸ å€ãäœã§ãããã¯æ確ã§ã¯ãããŸããã ããã€ãã®çµæãããŒãã³ãŒããããå€ãšæ¯èŒããããšããå§ãããŸãã äŸãã°ã
assert SomethingSerializer(old_somethings, many=True).data == {'blah':'blah'}
@rpkilbyãåçããããšã
for old_something in old_somethings:
old_something.refresh_from_db()
以åã®ã³ã¡ã³ããåé€ããå¿ èŠããããŸããããããšãä»ã®èª°ããåã誀æ€ç¥ãçµéšããå Žåã«åããŠã³ã¡ã³ããæ®ãå¿ èŠããããŸããïŒ
ããã«ã¡ã¯@ diegueus9 ãå¿é
ãããŸãã- details
ã¿ã°ã«ã³ãŒããé ããã ãã§ãã
æãåèã«ãªãã³ã¡ã³ã
ãã®æ©èœãããã ããã°å¹žãã§ãã æšæºã®Djangoã®åäœãšåæ§ã«ã
USE_TZ
èšå®ãå°éããå€ãå€æããå¿ èŠããããšæããŸãã