尝试为 YAML 数据设定种子时获取"value must be an integer"



我正在使用Django 2,Python 3.7和django地址模块(https://pypi.org/project/django-address/(。 我正在尝试插入一些种子数据。 我有这个 YAML ...

- model: address.locality
pk: 1
fields:
name: "Chicago"
postal_code: "60053"
state:
name: IL
country:
- United States

当我运行种子命令时

python manage.py loaddata maps/fixtures/seed_data.yaml

我收到此错误...

localhost:web davea$ python manage.py loaddata maps/fixtures/seed_data.yaml
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 923, in to_python
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'dict'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/python.py", line 157, in Deserializer
data[field.attname] = model._meta.get_field(field_name).to_python(field_value)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 928, in to_python
params={'value': value},
django.core.exceptions.ValidationError: ["'{'name': 'IL', 'country': ['United States']}' value must be an integer."]
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 335, in execute
output = self.handle(*args, **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 72, in handle
self.loaddata(fixture_labels)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 113, in loaddata
self.load_label(fixture_label)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 168, in load_label
for obj in objects:
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/pyyaml.py", line 73, in Deserializer
yield from PythonDeserializer(yaml.load(stream, Loader=SafeLoader), **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/python.py", line 159, in Deserializer
raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value)
django.core.serializers.base.DeserializationError: Problem installing fixture '/Users/davea/Documents/workspace/chicommons/maps/web/maps/fixtures/seed_data.yaml': ["'{'name': 'IL', 'country': ['United States']}' value must be an integer."]: (address.locality:pk=1) field_value was '{'name': 'IL', 'country': ['United States']}'

我已将其添加到文件映射/monkey_patching.py中,以帮助根据唯一标识符自动创建实体......

from address import State
from address import Country
def country_get_by_natural_key(self, name):
return self.get_or_create(name=name)[0]
def state_get_by_natural_key(self, name, country_id):
return self.get_or_create(name=name, country_id=country_id)[0]
Country.add_to_class("get_by_natural_key",country_get_by_natural_key)
State.add_to_class("get_by_natural_key",state_get_by_natural_key)

编辑:包括每个希瓦姆请求的堆栈跟踪...

(venv) localhost:maps davea$ python web/manage.py loaddata web/maps/fixtures/seed_data.yaml 
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 923, in to_python
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/python.py", line 157, in Deserializer
data[field.attname] = model._meta.get_field(field_name).to_python(field_value)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 928, in to_python
params={'value': value},
django.core.exceptions.ValidationError: ["'['IL', 'United States']' value must be an integer."]
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "web/manage.py", line 21, in <module>
main()
File "web/manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 335, in execute
output = self.handle(*args, **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 72, in handle
self.loaddata(fixture_labels)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 113, in loaddata
self.load_label(fixture_label)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/loaddata.py", line 168, in load_label
for obj in objects:
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/pyyaml.py", line 73, in Deserializer
yield from PythonDeserializer(yaml.load(stream, Loader=SafeLoader), **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/python.py", line 159, in Deserializer
raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value)
django.core.serializers.base.DeserializationError: Problem installing fixture '/Users/davea/Documents/workspace/chicommons/maps/web/maps/fixtures/seed_data.yaml': ["'['IL', 'United States']' value must be an integer."]: (address.locality:pk=1) field_value was '['IL', 'United States']'

自然键问题

get_by_natural_key方法在管理器级别可用,但您正在模型级别添加方法。因此,您需要这样做,而不是上述操作:

from django.db import models
from address.models import State
class CustomManager(models.Manager):
def get_by_natural_key(self, name):
return self.get_or_create(name=name)[0]
State.add_to_class('objects', CustomManager())

夹具问题

夹具的嵌套数据应仅包含参数,而不应包含 kwarg。检查 seed_data.yaml 文件中是否有办法自动生成第一个模型所依赖的模型?了解更多详情。之后,您需要相应地设计get_by_natural_key功能。所以对于locality模型夹具看起来像

- model: address.locality
pk: 1
fields:
name: "Chicago"
postal_code: "60053"
state: ['I', 'United States']

被覆盖的经理将是

class CustomManager(models.Manager):
def get_by_natural_key(self, state_name, country):
country = Country.objects.get_or_create(name=country)[0]
return State.objects.get_or_create(name=state_name, country=country)[0]
setattr(State._meta, 'default_manager', CustomManager())

我会提供另一种方法,即编写自己的管理命令来导入此数据,而不是尝试使loaddata工作 - 我认为这可能会少得多的努力。

此命令适用于您提供的示例数据 - 如果 YAML 文件中的不仅仅是address.locality对象,则可能需要进行一些小的调整:

import yaml
from django.core.management.base import BaseCommand
from address.models import Country, State, Locality

class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('file', nargs=1, type=str)
def handle(self, *args, **options):
f = options['file'][0]
with open(f, 'r') as yamlfile:
data = yaml.load(yamlfile)
for row in data:
if row['model'] == 'address.locality':
state_name = row['fields']['state']['name']
country_name = row['fields']['state']['country'][0]
country_obj, _ = Country.objects.get_or_create(name=country_name)
state_obj, _ = State.objects.get_or_create(country=country_obj, name=state_name)
Locality.objects.get_or_create(
pk=row['pk'], 
state=state_obj, 
postal_code=row['fields']['postal_code'], 
name=row['fields']['name']
)

(旁注 - 您的 YAML 格式有点奇怪,因为它提供了一个country列表。我以为一个国家只能属于一个国家?

在此包的源代码中,Locality.state字段通过foreignKeyState模型相关。因此,您的数据装置state字段必须是相关表名的整数。

参见 django 地址源代码

PS:在您的情况下,您必须构建与Locality模型相关的所有相关模型。如果没有,您将遇到数据完整性错误...以及所有其他错误。

最新更新