I am creating model which needs to store a timezone value. Right now, I am generating the timezones using pytz
in another file, converting that into a tuple, and calling that tuple into my models.py. Like this:
timezones.py
import pytz
TIMEZONE_CHOICES = []
for tz in pytz.all_timezones:
TIMEZONE_CHOICES.append((tz, tz))
TIMEZONE_CHOICES = tuple(TIMEZONE_CHOICES)
models.py
from .timezones import TIMEZONE_CHOICES
class MyModel(models.Model):
timezone = models.CharField(max_length=255, default='UTC', choices=TIMEZONE_CHOICES)
This honestly seems a bit hack-y. Would generating the timezones this way cause problems in the future? What would be the ideal way to do something like this?
If Django allowed choices to accept callables you could simply pass a lambda
function. But since it doesn't (yet), you should be able to simply define the choices list within your model class and use the zip
function to dynamically generate the tuples. For example:
import pytz
class MyModel(models.Model):
TIMEZONE_CHOICES = zip(pytz.all_timezones, pytz.all_timezones)
timezone = models.CharField(max_length=255, default='UTC', choices=TIMEZONE_CHOICES)
The only issue I can see is that if a timezone is removed from the tz
database in the future, the select box would be empty when you try to edit such a record.
Update: Django 5.0 and above now supports callables:
Django 5.0 adds support for accepting a mapping or a callable instead of an iterable
def get_scores(): return [(i, str(i)) for i in range(10)] class Winner(models.Model): ... score = models.IntegerField(choices=get_scores)