django_address 模块是否提供了一种为初始国家数据做种的方法?

Dav*_*ave 6 python django seeding python-3.x

我正在使用 Django 2.0、Python 3.7 和 MySql 5。我最近安装了 django_address 模块。我注意到当我根据我的 models.py 文件运行我的初始迁移时......

from django.db import models

from address.models import AddressField
from phonenumber_field.modelfields import PhoneNumberField


class CoopType(models.Model):
    name = models.CharField(max_length=200, null=False)

    class Meta:
        unique_together = ("name",)


class Coop(models.Model):
    type = models.ForeignKey(CoopType, on_delete=None)
    address = AddressField(on_delete=models.CASCADE)
    enabled = models.BooleanField(default=True, null=False)
    phone = PhoneNumberField(null=True)
    email = models.EmailField(null=True)
    web_site = models.TextField()
Run Code Online (Sandbox Code Playgroud)

它创建了一些地址表,包括...

mysql> show create table address_country;
+-----------------+---------------------------------------------------+
| Table           | Create Table                                      |
+-----------------+---------------------------------------------------+
| address_country | CREATE TABLE `address_country` (                  |
|                 |   `id` int(11) NOT NULL AUTO_INCREMENT,           |
|                 |   `name` varchar(40) COLLATE utf8_bin NOT NULL,   |
|                 |   `code` varchar(2) COLLATE utf8_bin NOT NULL,    |
|                 |   PRIMARY KEY (`id`),                             |
|                 |   UNIQUE KEY `name` (`name`)                      |
|                 | ) ENGINE=InnoDB                                   |
|                 | DEFAULT CHARSET=utf8 COLLATE=utf8_bin             |
+-----------------+---------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

但是,该表中没有数据。有没有办法获取模块生成的表的种子数据,还是需要自己挖掘?

bdo*_*leu 5

pycountry您可以使用该软件包轻松地自己生成国家/地区。

由于创建的模型code上的字段Country的最大长度为两个字符,因此您将需要使用该alpha_2代码。

我通常使用自定义管理命令来处理此类事情。也许添加一个检查以查看是否已创建任何对象,然后根据需要进行处理。

从 shell 中使用python manage.py create_countries

from address.models import Country
from pycountry import countries
from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'Initialize Country model'

    def handle(self, *args, **kwargs):
        create_countries = [
            Country(name=country.name[:40], code=country.alpha_2)
            for country in countries
        ]
        Country.objects.bulk_create(create_countries)
        self.stdout.write(f'Created {len(countries)} countries.\n')
Run Code Online (Sandbox Code Playgroud)

如果生产服务器未运行 Python/Django,那么您可以使用pycountry相关数据创建 CSV 文件。假设您使用的是 PostgreSQL,那么您可以使用该COPY FROM命令来填充数据库。

import csv
from pycountry import countries

with open('countries.csv', mode='w') as countries_file:
    # specify delimiter because some countries have a comma
    writer = csv.writer(countries_file, delimiter='\t')
    writer.writerow(['id', 'name', 'code'])
    writer.writerows([
        [index + 1, country.name, country.alpha_2]
        for index, country in enumerate(countries)
    ])
Run Code Online (Sandbox Code Playgroud)


sol*_*oke 0

我建议您编写一个简单的管理命令,将数据从pycountry导入到您的地址模型中(从此处借用的方法)。pycountry 是 ISO 标准国家列表的包装 - 也就是说,它是您将获得的最规范的国家列表。

将所有国家/地区填充到模型中的管理命令如下Country所示:

import pycountry
from django.core.management.base import BaseCommand, CommandError

from address.models import Country

class Command(BaseCommand):
    help = "Populates address.Country with data from pycountry."

    def handle(self, *args, **options):
        countries = [
            Country(
                code=country.alpha_2,
                name=country.name[:40],  # NOTE - concat to 40 chars because of limit on the model field
            )
            for country in pycountry.countries
        ]

        Country.objects.bulk_create(countries)
        self.stdout.write("Successfully added %s countries." % len(countries))
Run Code Online (Sandbox Code Playgroud)

这将使用 ISO 国家/地区列表填充您的模型。

这里需要注意的是,该address.Country.name字段限制为 40 个字符(对我来说,这似乎是一个值得怀疑的设计决策,以及不使国家/地区代码唯一的决定 - ISO 2 字母代码绝对是唯一的),因此上面的脚本截断了名称要适合。如果这对您来说是个问题,我建议您建立自己的地址模型,借用django-address并提高字符限制。