Search code examples
djangodjango-models

What is the best way to have all the timezones as choices for a Django model?


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?


Solution

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