我有一个地址信息表格。其中一个字段用于地址国家/地区。目前这只是一个文本框。我想要一个下拉列表(ISO 3166 国家)。我是 django 新手,所以我什至还没有使用 Django Select 小部件。有什么好方法可以做到这一点?
将文件中的选项硬编码到某处?将它们放入数据库中?在模板中?
我有一个地址信息表格。其中一个字段用于地址国家/地区。目前这只是一个文本框。我想要一个下拉列表(ISO 3166 国家)。我是 django 新手,所以我什至还没有使用 Django Select 小部件。有什么好方法可以做到这一点?
将文件中的选项硬编码到某处?将它们放入数据库中?在模板中?
查看 CharField 的“选择”参数。
您可能还想看看django-countries。
from django_countries.fields import CountryField
class Foo(models.Model):
country = CountryField()
最后使用下面的代码片段,它基本上定义了一个由两个字符国家代码组成的元组。此外,它定义了一个名为 CountryField 的自定义字段类型,并将选择参数默认为上述定义的元组。这会自动呈现为下拉列表。
姜戈国家
from django_countries.countries import COUNTRIES
class CountryForm(forms.Form):
country= forms.ChoiceField(COUNTRIES)
两个低维护项目:
http://code.google.com/p/django-countries/
https://github.com/strange/django-country-utils
两个片段:
http://djangosnippets.org/snippets/494/
http://djangosnippets.org/snippets/1476/
现在,我要找一个片段。
正如之前的答案所述,有一个CountryField
in django-countries
。这是一个模型字段。
如果需要以普通形式(不是模型形式)的表单字段,在django-countries
v3.x(肯定在 3.3 中测试)中可以使用以下内容:
from django_countries.data import COUNTRIES
class MyForm(forms.Form):
country = forms.ChoiceField(sorted(COUNTRIES.items()))
这是一个带有国家(不仅是)的不错的图书馆:pycountry
与其他解决方案中的硬编码国家相比,它的主要优点是它是 Debian 软件包 pkg-isocodes 的包装器(因此可以自动更新)。它也有翻译。
因此,如果出现新国家或现有国家将合并在一起,您无需更改代码。
我发现使用这个库并使用模型 Country 创建一个简单的 Django 应用程序很有用,例如
然后,您可以通过自定义 django-admin 命令填充并保持最新的“国家”表,如下所述:编写自定义 django-admin 命令
Django 使用pytz
(参见例如django.utils.timezone),并pytz
公开一个country_names
基于 ISO 3166 的字典(参见 pytz 文档)。
该pytz.country_names
字典可用于设置模型字段选择或表单字段选择。
这可能不会涵盖所有边缘情况,但至少它不会向您的 Django 项目添加另一个模糊的外部依赖项。
模型字段的示例(import pytz
第一个):
country = models.CharField(max_length=2, choices=pytz.country_names.items())
请注意,dict 键(国家代码)都是大写字母。
要记住的另一件事,以防pytz
更新:如 Django模型字段参考中所述
每次
choices
更改顺序时都会创建一个新迁移。
将它们放入数据库是一种更好的方法。便于管理。
我通过使用解决了它multiple=True
:
from django_countries.fields import CountryField
class UserProfile(models.Model):
countries = CountryField(multiple=True)
您可以在文档中阅读更多相关信息:
链接到包:django-countries
如果在表格中寻找如何做到这一点:
$ pip install django-countries
>>> from django_countries.data import COUNTRIES
>>> Country = forms.ChoiceField(choices = sorted(COUNTRIES.items()))
这是解决方案:
from django_countries.fields import CountryField
class Foo(TimeStampedModel):
country = CountryField()
SmileyChris 似乎很忙且无法使用,因为存储库自 9 月以来一直没有更新。值得庆幸的是,有一个可以分叉的存储库,它与 Django 3 及更高版本兼容。这可以在这里找到:
https://github.com/yunojuno/django-countries/tree/django-30
它通过了拉取请求的所有检查,但是 SmileyChris 没有响应合并请求。
要安装它,只需运行pip install git+https://github.com/yunojuno/django-countries.git
如果您正在扩展 forms.Form 类,那么您必须在 Countryfield 之后指定 .formfield ,然后在 formfield() 参数中指定您的属性。
from django_countries.fields import CountryField
class CheckOutForm(forms.Form):
country = CountryField().formfield()
但是,如果您是从 models.Model 类扩展,那么定义 Coutryfield 就足够了。
from django_countries.fields import CountryField
class CheckOutForm(models.Model):
country = CountryField()
我想,Django 没有尝试使用诸如ChoiceField
or之类的模型字段CharField
并将“选择”作为参数传递,该参数包含国家列表作为在 models.py 外部创建的列表中的元组值,Django 有一个紧凑的库,可以在填充时选择国家表格。
from django-countries.fields import CountryField
class foo(models.Model):
country = CountryField(blank_label='select country')
...
如果您只想在没有安装django-choices的情况下拥有一个国家 ChoiceField ,您可以创建一个额外的文件,其中包含一个包含来自Wikipedia Iso Country Codes的所有选项的元组:
import csv
# Get the file from: "http://geohack.net/gis/wikipedia-iso-country-codes.csv"
with open("wikipedia-iso-country-codes.csv") as f:
file = csv.DictReader(f, delimiter=',')
country_names = [line['English short name lower case'] for line in file]
# Create a tuple with the country names
with open("country_names.py", 'w') as f:
f.write('COUNTRY_CHOICES = (\n')
for c in country_names:
f.write(f' ("{c}", "{c}"),\n')
f.write(')')
创建的 country_names.py 文件如下所示:
COUNTRY_CHOICES = (
("Afghanistan", "Afghanistan"),
("Åland Islands", "Åland Islands"),
("Albania", "Albania"),
("Algeria", "Algeria"),
("American Samoa", "American Samoa"),
...
)
然后,您可以像这样在表单中使用 COUNTRY_CHOICES:
from django import forms
from country_names import COUNTRY_CHOICES
class CountryForm(forms.Form):
country= forms.ChoiceField(choices=COUNTRY_CHOICES)