Django: Country drop down list?
-
19-04-2021 - |
質問
I have a form for address information. One of the fields is for the address country. Currently this is just a textbox. I would like a drop down list (of ISO 3166 countries) for this. I'm a django newbie so I haven't even used a Django Select widget yet. What is a good way to do this?
Hard-code the choices in a file somewhere? Put them in the database? In the template?
解決
from django_countries.fields import CountryField
class Foo(models.Model):
country = CountryField()
他のヒント
Check out "choices" parameter of a CharField.
You might also want to take a look at django-countries.
Ended up using the below snippet which basically defines a tuple of tuples of two character country codes. Additionally it defines a custom field type called CountryField and defaults the choices parameter to the above defined tuple. This automatically gets rendered as a drop down list.
Django Countries
from django_countries.countries import COUNTRIES
class CountryForm(forms.Form):
country= forms.ChoiceField(COUNTRIES)
Two low mantained projects:
http://code.google.com/p/django-countries/
https://github.com/strange/django-country-utils
Two snippets:
http://djangosnippets.org/snippets/494/
http://djangosnippets.org/snippets/1476/
For now, I am going for a snippet.
Here is a nice library with countries (and not only): pycountry
Its main advantage is that it is a wrapper around Debian package pkg-isocodes (thus can updates automatically with it) compared to hard-coded countries in other solutions. It also has translations.
So if new country appears or existing countries will be merged together you do not need to change your code.
I found it useful to use this library and create a simple Django app with model Country for example
Then you can populate and keep up-to-date your 'country' table by means of custom django-admin command as described here: Writing custom django-admin commands
As previous answers have stated, there is a CountryField
in django-countries
. This is a model field.
If a form field is needed in a plain form (not model form), in django-countries
v3.x (definitely tested in 3.3) the following can be used:
from django_countries.data import COUNTRIES
class MyForm(forms.Form):
country = forms.ChoiceField(sorted(COUNTRIES.items()))
Django 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.
Put them in the database is a better way. Convenient to management.
I solved it by using multiple=True
:
from django_countries.fields import CountryField
class UserProfile(models.Model):
countries = CountryField(multiple=True)
You can read more about it in the docs:
Link to package : django-countries
If looking for how to do it in forms :
$ pip install django-countries
>>> from django_countries.data import COUNTRIES
>>> Country = forms.ChoiceField(choices = sorted(COUNTRIES.items()))
Here is the solution:
from django_countries.fields import CountryField
class Foo(TimeStampedModel):
country = CountryField()
SmileyChris seems to be pretty busy and unavailable, as the repository hasn't been updated since September. Thankfully, there is a repository that can be forked that is compatible with Django 3 and higher. This can be found here:
https://github.com/yunojuno/django-countries/tree/django-30
It passes all checks for a pull request, however SmileyChris has not responded to the merge request.
To install it just run pip install git+https://github.com/yunojuno/django-countries.git
If you are extending forms.Form class then you have to specify .formfield right after your Countryfield and then specify your attributes in formfield() parameter.
from django_countries.fields import CountryField
class CheckOutForm(forms.Form):
country = CountryField().formfield()
But if you are extending from models.Model class then defining Coutryfield is enough.
from django_countries.fields import CountryField
class CheckOutForm(models.Model):
country = CountryField()