UPDATE (Django >=4.0)
Using pytz.country_names
was convenient in older Django versions, as described below, but Django >=4.0 uses zoneinfo
instead of pytz
. Details in the release notes and here.
Unfortunately, zoneinfo
does not appear to offer an equivalent of pytz.country_names
(as far as I know).
There is, however, an up-to-date list of ISO 3166 country names in Python's (first-party) tzdata
package: iso3166.tab
Note that tzdata
is already installed if you're using Django 4+ on Windows.
For illustrative purposes only, here's a quick & dirty way to parse the iso3166.tab file into a dict
similar to pytz.country_names
(Python 3.9+):
from importlib import resources
with resources.files('tzdata.zoneinfo').joinpath('iso3166.tab').open('r') as f:
country_names = dict(
line.rstrip('\n').split('\t', 1)
for line in f
if not line.startswith('#')
)
Note, for Django's field choices
, it would be easier to create a list
directly, instead of a dict
.
ORIGINAL (Django <4.0)
Django (<4.0) uses pytz
(see e.g. django.utils.timezone), and pytz
exposes a country_names
dictionary, based on ISO 3166 (see pytz docs).
This pytz.country_names
dictionary can be used to set your model field choices, or form field choices.
This might not cover all edge cases, but, at least, it does not add another obscure external dependency to your Django project.
Example for a model field (import pytz
first):
country = models.CharField(max_length=2, choices=pytz.country_names.items())
Note that the dict keys (country codes) are all capitals.
One other thing to keep in mind, in case pytz
is updated: as mentioned in the Django Model field reference
A new migration is created each time the order of choices
changes.