Django FK 约束投诉,但对象在那里。我想念啥?
Posted
技术标签:
【中文标题】Django FK 约束投诉,但对象在那里。我想念啥?【英文标题】:Dajango FK constraint complaint, but object is there. What do I miss?Django FK 约束投诉,但对象在那里。我想念什么? 【发布时间】:2022-01-05 13:51:24 【问题描述】:我正在使用我的第一个 Django 应用程序,请多多包涵……
它基于一些带有现有 PostgreSQL 数据库的遗留脚本。因此,某些表的命名不遵循 Django 命名模式。
目前我正在重塑我的数据以遵循健全的数据建模原则。执行其中一个步骤的迁移给了我一个我不明白的外键异常:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 242, in _commit
return self.connection.commit()
psycopg2.errors.ForeignKeyViolation: insert or update on table "design_shopify_category" violates foreign key constraint "design_shopify_categ_shopifycollection_id_9f310876_fk_designs_s"
DETAIL: Key (shopifycollection_id)=([<ShopifyCollection: ShopifyCollection object (gid://shopify/Collection/263596736569)>]) is not present in table "designs_shopifycollection".
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/local/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/root/.vscode-server/extensions/ms-python.python-2021.11.1422169775/pythonFiles/lib/python/debugpy/__main__.py", line 45, in <module>
cli.main()
File "/root/.vscode-server/extensions/ms-python.python-2021.11.1422169775/pythonFiles/lib/python/debugpy/../debugpy/server/cli.py", line 444, in main
run()
File "/root/.vscode-server/extensions/ms-python.python-2021.11.1422169775/pythonFiles/lib/python/debugpy/../debugpy/server/cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "/usr/local/lib/python3.9/runpy.py", line 268, in run_path
return _run_module_code(code, init_globals, run_name,
File "/usr/local/lib/python3.9/runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/usr/local/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/workspace/src/otaya_tool/manage.py", line 23, in <module>
main()
File "/workspace/src/otaya_tool/manage.py", line 19, in main
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.9/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.9/site-packages/django/core/management/__init__.py", line 413, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 354, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 398, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 89, in wrapped
res = handle_func(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/core/management/commands/migrate.py", line 244, in handle
post_migrate_state = executor.migrate(
File "/usr/local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 230, in apply_migration
migration_recorded = True
File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/schema.py", line 120, in __exit__
self.atomic.__exit__(exc_type, exc_value, traceback)
File "/usr/local/lib/python3.9/site-packages/django/db/transaction.py", line 246, in __exit__
connection.commit()
File "/usr/local/lib/python3.9/site-packages/django/utils/asyncio.py", line 33, in inner
return func(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 266, in commit
self._commit()
File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 242, in _commit
return self.connection.commit()
File "/usr/local/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 242, in _commit
return self.connection.commit()
django.db.utils.IntegrityError: insert or update on table "design_shopify_category" violates foreign key constraint "design_shopify_categ_shopifycollection_id_9f310876_fk_designs_s"
DETAIL: Key (shopifycollection_id)=([<ShopifyCollection: ShopifyCollection object (gid://shopify/Collection/263596736569)>]) is not present in table "designs_shopifycollection".
有两个模型,与错误相关:
class ShopifyCollection(models.Model):
graph_ql_id = models.CharField(max_length=250, primary_key=True,
validators=[validate_sy_graph_ql_id])
handle = models.CharField(max_length=250, blank=False, null=False,
validators=[validate_slug])
title = models.CharField(max_length=250, blank=False, null=False)
def pk_uuid_gen() -> str:
return str(uuid4())
class Design(models.Model):
uuid = models.CharField(primary_key=True, unique=True, default=pk_uuid_gen,
editable=False, max_length=36)
niche = models.CharField(blank=False, null=True, max_length=50)
id = models.CharField(blank=False, null=True, max_length=4)
variant = models.CharField(blank=False, null=True, max_length=1)
language = models.CharField(max_length=2, default=None)
# the new many 2 many relation to be filled by the migration.
shopify_category = models.ManyToManyField(ShopifyCollection, blank=True)
# the legacy field to get the values from...
shopify_category_tmp = models.JSONField(blank=True, default=empty_development_default)
class Meta:
db_table = 'design'
unique_together = ((niche', 'id', 'variant'),)
这是迁移代码:
# Generated by Django 3.2.9 on 2021-11-27 18:00
from django.db import migrations
from django.core.exceptions import ObjectDoesNotExist
from designs.models import Design, ShopifyCollection
def convert_shopify_category_json_objects_to_m2m(apps, schema_editor):
# this doesn't give an error. It's the exact same key the FK exception
# complains about. It's also the first object it want's to add.
x = ShopifyCollection.objects.get(pk='gid://shopify/Collection/263596736569')
for design in Design.objects.all().iterator():
if len(design.shopify_category_tmp) == 0:
continue
# the legacy field holds a list of strings like: ["archery", "outdoor"]
for category in design.shopify_category_tmp:
if len(category) == 0:
continue
sy_col_handles = [
f'niche-de-category',
f'featured-de-category']
sy_collections = []
for handle in sy_col_handles:
try:
sy_collections.append(ShopifyCollection.objects.get(handle=handle))
except ObjectDoesNotExist:
pass
if len(sy_collections) < 1:
raise ValueError('There are no Shopify Collections for the handles ' +
f'sy_col_handles. We need at least one of them.')
design.shopify_category.add(sy_collections)
design.save()
class Migration(migrations.Migration):
dependencies = [
('designs', '0031_shopify_categories_link_them'),
]
operations = [
migrations.RunPython(convert_shopify_category_json_objects_to_m2m),
]
表designs_shopifycollection
在迁移的数据库事务开始之前保存gid://shopify/Collection/263596736569
行,异常抱怨丢失。
x = ShopifyCollection.objects.get(pk='gid://shopify/Collection/263596736569')
行也证明该表包含迁移的 db 事务中请求的行。
该表还包含迁移后的“缺失”行。
我尝试通过 Django 框架代码调试问题,但过了一段时间就停止了。找不到比提交触发的异常更多...
还可以手动将行添加到 m2n 表中,没有任何问题,并显示为在 DesignFrom 视图中选择。
我的想法已经用完了。问题出在哪里?
【问题讨论】:
【参考方案1】:您需要将项目作为单独的参数传递,所以:
# asterisk ↓
design.shopify_category.add(*sy_collections)
【讨论】:
谢谢,就是这样。如果我没记错的话,* 正在展开它...... @andreas: 是的,如果sy_collections
具有例如三个元素a
、b
和c
,它用.add(a, b, c)
调用它。
如果能更好地验证允许卡在 .add() 方法中的内容,那就太好了。但我想在这里从无效中识别价值并不容易......以上是关于Django FK 约束投诉,但对象在那里。我想念啥?的主要内容,如果未能解决你的问题,请参考以下文章
Django ORM:未继承子级的字段和值。对象重复。 (使用Django管理界面)
SonarQube 投诉要么删除这个无用的类对象实例化,要么使用它