如何解决复杂的 Django CheckContraint 不会迁移
我在运行包含有点复杂的 CheckConstraint
的 Django (2.2) 迁移时遇到问题,该迁移在 python 3.6.9 上运行。
底层数据库为 PostGIS 9.5。
模型:
class Subscription(BaseModel):
class Meta:
constraints = [
models.CheckConstraint(name='%(app_label)s_%(class)s_valid_product',check=(
(models.Q(variant_id__exact=None) & models.Q(product_id__exact=None)) |
(~models.Q(variant_id__exact=None) & ~models.Q(product_id__exact=None))
))
]
...
product_id = models.IntegerField()
variant_id = models.IntegerField()
迁移:
...
migrations.AddConstraint(
model_name='subscription',constraint=models.CheckConstraint(
name='%(app_label)s_%(class)s_valid_product',check=models.Q(
models.Q(
models.Q(variant_id__exact=None),models.Q(product_id__exact=None)
),models.Q(
models.Q(_negated=True,variant_id__exact=None),models.Q(_negated=True,product_id__exact=None)
),_connector='OR'
)
),),...
还有很大的坏痕迹:
File "./manage.py",line 10,in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.6/site-packages/django/core/management/__init__.py",line 381,in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.6/site-packages/django/core/management/__init__.py",line 375,in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.6/site-packages/django/core/management/base.py",line 323,in run_from_argv
self.execute(*args,**cmd_options)
File "/usr/local/lib/python3.6/site-packages/django/core/management/base.py",line 364,in execute
output = self.handle(*args,**options)
File "/usr/local/lib/python3.6/site-packages/django/core/management/base.py",line 83,in wrapped
res = handle_func(*args,**kwargs)
File "/usr/local/lib/python3.6/site-packages/django/core/management/commands/migrate.py",line 234,in handle
fake_initial=fake_initial,File "/usr/local/lib/python3.6/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.6/site-packages/django/db/migrations/executor.py",line 147,in _migrate_all_forwards
state = self.apply_migration(state,migration,line 245,in apply_migration
state = migration.apply(state,schema_editor)
File "/usr/local/lib/python3.6/site-packages/django/db/migrations/migration.py",line 124,in apply
operation.database_forwards(self.app_label,schema_editor,old_state,project_state)
File "/usr/local/lib/python3.6/site-packages/django/db/migrations/operations/models.py",line 827,in database_forwards
schema_editor.add_constraint(model,self.constraint)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/schema.py",line 345,in add_constraint
self.execute(sql)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/schema.py",line 137,in execute
cursor.execute(sql,params)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py",line 99,in execute
return super().execute(sql,line 67,in execute
return self._execute_with_wrappers(sql,params,many=False,executor=self._execute)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py",line 76,in _execute_with_wrappers
return executor(sql,many,context)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py",line 84,in _execute
return self.cursor.execute(sql,params)
TypeError: tuple indices must be integers or slices,not str
迁移是自动生成的。我只是格式化它看起来更漂亮。 任何帮助表示赞赏
编辑:我注意到那些 __str__
的 Q-expressions
表示不同:
来自模型:
(OR:
(AND:
('variant_id__exact',None),('product_id__exact',None)
),(AND:
(NOT
(AND:
('variant_id__exact',None)
)
),(NOT
(AND:
('product_id__exact',None)
)
)
)
)
来自迁移:
(OR:
(AND:
(AND:
('variant_id__exact',None)
),(AND:
('product_id__exact',None)
)
),None)
)
)
)
)
我将尝试验证这些在 PostgreSQL 中是否有效。
解决方法
结果是问题在于约束名称
正如一位同事所指出的:
我发现 '%(app_label)s'
和 '%(class)s'
已添加到 Django 3.0 中,而我们在 Django 2.2 上!
一旦我摆脱了这些,迁移就会正确运行。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。