2

Django timezone fields are built upon pytz timezones, but some of the timezones of the latter are not valid for the fields. With a model like

from django.db import models
from timezone_field import TimeZoneField

class TestModel(models.Model):
    timezone_field = TimeZoneField(default='UTC')

def save(self, *args, **kwargs):
    self.clean()
    self.full_clean()
    super().save(*args, **kwargs)

If I run (in a shell)

import pytz
from models import TestModel

model = TestModel.objects.get(id=1)

for zone in pytz.all_timezones:
    model.timezone = zone
    model.save()

I get

django.core.exceptions.ValidationError: {'timezone': ["Value <DstTzInfo 'Africa/Asmera' LMT+2:27:00 STD> is not a valid choice."]}

So it fails first on 'Africa/Asmera' (it fails on others too, e.g. 'GMT+0').

Any idea of how to resolve this inconsistency? At the moment the user can select a timezone on the frontend that will give a backend error (the frontend is built in React and gets the timezones from moment timezone)

jorgen
  • 3,425
  • 4
  • 31
  • 53

1 Answers1

4

As Willem mentioned in V1.2 of Django Timezone Fields, they changed the field's default choices from all_timezones to common_timezones. You can revert this change by explicitly setting the choices attribute in the field definition.

https://github.com/mfogel/django-timezone-field

1.2 (2015-02-05) For form field, changed default list of accepted timezones from pytz.all_timezones to pytz.common_timezones, to match DB field behavior. 1.1 (2014-10-05) Django 1.7 compatibility Added support for formating choices kwarg as [[, ], ...], in addition to previous format of [[, ], ...]. Changed default list of accepted timezones from pytz.all_timezones to pytz.common_timezones. If you have timezones in your DB that are in pytz.all_timezones but not in pytz.common_timezones, this is a backward-incompatible change. Old behavior can be restored by specifying choices=[(tz, tz) for tz in pytz.all_timezones] in your model definition.

class TestModel(models.Model):
    timezone_field = TimeZoneField(default='UTC', choices=[(tz, tz) for tz in pytz.all_timezones])

There is a disclaimer about this being a backwards incompatible change; so I urge you to look into this further

rtindru
  • 5,107
  • 9
  • 41
  • 59