我使用的是django 3。sqlite数据库。我遇到一种情况,其中一个模型中的实例无法保存。我得到一个完整性错误和"CHECK约束失败",后面跟着我的模型名称("post"在我的"压力"下;应用:press_post)。我已经查过了,我想这意味着我的一个字段的值是不可能的?如果有人能更准确、更精确地解释它的意思,那就很有帮助了。大多数情况下,我想知道如何找出哪个检查约束失败了,以便修复它(模型中的哪个字段或哪个数据块导致了问题)。模型中的其他实例保存没有任何问题,而其他一些实例存在与此实例相同的问题。
我可以访问shell_plus中的实例并查看数据。看起来还行……但显然我遗漏了一些东西。
错误输出:
---------------------------------------------------------------------------
IntegrityError Traceback (most recent call last)
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)
83 else:
---> 84 return self.cursor.execute(sql, params)
85
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py in execute(self, query, params)
422 query = self.convert_query(query)
--> 423 return Database.Cursor.execute(self, query, params)
424
IntegrityError: CHECK constraint failed: press_post
The above exception was the direct cause of the following exception:
IntegrityError Traceback (most recent call last)
<ipython-input-8-0c61e89703f4> in <module>
----> 1 post.save()
~/pastrami/pastrami/press/models.py in save(self, *args, **kwargs)
438 # postreport_check(self)
439
--> 440 super(Post, self).save(*args, **kwargs)
441
442 # tags
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/base.py in save(self, force_insert, force_update, using, update_fields)
724 update_fields = frozenset(loaded_fields)
725
--> 726 self.save_base(using=using, force_insert=force_insert,
727 force_update=force_update, update_fields=update_fields)
728 save.alters_data = True
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/base.py in save_base(self, raw, force_insert, force_update, using, update_fields)
761 if not raw:
762 parent_inserted = self._save_parents(cls, using, update_fields)
--> 763 updated = self._save_table(
764 raw, cls, force_insert or parent_inserted,
765 force_update, using, update_fields,
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/base.py in _save_table(self, raw, cls, force_insert, force_update, using, update_fields)
843 for f in non_pks]
844 forced_update = update_fields or force_update
--> 845 updated = self._do_update(base_qs, using, pk_val, values, update_fields,
846 forced_update)
847 if force_update and not updated:
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/base.py in _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update)
897 (filtered._update(values) > 0 or filtered.exists())
898 )
--> 899 return filtered._update(values) > 0
900
901 def _do_insert(self, manager, using, fields, returning_fields, raw):
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/query.py in _update(self, values)
800 query.annotations = {}
801 self._result_cache = None
--> 802 return query.get_compiler(self.db).execute_sql(CURSOR)
803 _update.alters_data = True
804 _update.queryset_only = False
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/sql/compiler.py in execute_sql(self, result_type)
1557 related queries are not available.
1558 """
-> 1559 cursor = super().execute_sql(result_type)
1560 try:
1561 rows = cursor.rowcount if cursor else 0
~/pastrami/rye/lib/python3.8/site-packages/django/db/models/sql/compiler.py in execute_sql(self, result_type, chunked_fetch, chunk_size)
1173 cursor = self.connection.cursor()
1174 try:
-> 1175 cursor.execute(sql, params)
1176 except Exception:
1177 # Might fail for server-side cursors (e.g. connection closed)
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/utils.py in execute(self, sql, params)
96 def execute(self, sql, params=None):
97 with self.debug_sql(sql, params, use_last_executed_query=True):
---> 98 return super().execute(sql, params)
99
100 def executemany(self, sql, param_list):
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/utils.py in execute(self, sql, params)
64
65 def execute(self, sql, params=None):
---> 66 return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
67
68 def executemany(self, sql, param_list):
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/utils.py in _execute_with_wrappers(self, sql, params, many, executor)
73 for wrapper in reversed(self.db.execute_wrappers):
74 executor = functools.partial(wrapper, executor)
---> 75 return executor(sql, params, many, context)
76
77 def _execute(self, sql, params, *ignored_wrapper_args):
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)
82 return self.cursor.execute(sql)
83 else:
---> 84 return self.cursor.execute(sql, params)
85
86 def _executemany(self, sql, param_list, *ignored_wrapper_args):
~/pastrami/rye/lib/python3.8/site-packages/django/db/utils.py in __exit__(self, exc_type, exc_value, traceback)
88 if dj_exc_type not in (DataError, IntegrityError):
89 self.wrapper.errors_occurred = True
---> 90 raise dj_exc_value.with_traceback(traceback) from exc_value
91
92 def __call__(self, func):
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)
82 return self.cursor.execute(sql)
83 else:
---> 84 return self.cursor.execute(sql, params)
85
86 def _executemany(self, sql, param_list, *ignored_wrapper_args):
~/pastrami/rye/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py in execute(self, query, params)
421 return Database.Cursor.execute(self, query)
422 query = self.convert_query(query)
--> 423 return Database.Cursor.execute(self, query, params)
424
425 def executemany(self, query, param_list):
IntegrityError: CHECK constraint failed: press_post
这是[edit: simplified]模型(只包括导致问题的字段)
class Post(models.Model):
doi = models.CharField(max_length=50, blank=True)
detailed_alts = models.JSONField(default=dict, blank=True)
alts = models.JSONField(default=dict, blank=True)
这是被[edit: simplified]覆盖的保存函数。
def save(self, *args, **kwargs): # when saving, update alts
if bool(self.doi) is True:
self.detailed_alts = self.get_alts['detailed']
self.alts = self.get_alts['simple']
[编辑]
我从有用的评论中意识到问题是在我的自定义保存函数中更新了两个字段。检查约束失败,因为对于某些实例,我要求为这些JSONFields设置一些不允许的东西:使用numpy (np.nan)
的nan值这里是代码的相关(冒犯)部分:我的模型的get_alts方法。
def get_alts(self):
if 'context' in detailed_alts:
[do stuff]
else:
alts['context'] = np.nan
alts['rank'] = np.nan
return {'detailed': detailed_alts, 'simple': alts}
对于"context"不在detailed_alts字典中的实例,我不能将更改保存到实例中,因为我已将值设置为np。nan,这在JSONField中是不允许的。改变np。nan到' nan '修复了问题。
至于这是如何计算出来的,我只需要尝试注释掉保存函数的部分,直到我击中导致保存失败的部分。然后,我测试了保存函数中的每一行,但在尝试保存之前从未出现错误。所以,我突然意识到问题可能出在json字段上,因为我以前在序列化日期时遇到过一次问题。
谢谢你的帮助。问题是,在我的自定义保存函数中,当评估一个条件时,我分配了一个np。将一个值赋给字典中的一个键,然后将该键赋给模型的一个json字段。显然这是不允许的。我猜jsonfields不能序列化np.nan。我不知道从长远来看该怎么做,但将它们更改为"NaN"文本是有效的。大多数实例没有问题的原因是大多数实例没有返回nan值。
在Google上按标题搜索(我搜索的是django determine what field caused check constraint to fail
),这个答案会出现在搜索结果的最前面(对我来说是第一个)。但实际上没有什么可以回答题目所提出的问题。
我终于能够通过深入调试PyCharm中的调用堆栈来找出导致问题的字段。在django.db.models.base.Model._do_insert
中,当我检查要插入的对象的值时,在进入manager._insert
之前,我发现在添加约束之前,我已经为字段提供了默认值,但是这些默认值现在与我的约束相冲突。因此,为了节省一些调试工作,我建议在_do_insert
中设置一个断点,并查看模型对象的字段值。