我正在使用 django 3. sqlite 数据库。我有一种情况,其中一个模型中的实例无法保存。我收到一个完整性错误和“CHECK 约束失败”,然后是我的模型名称(我的“press”应用程序中的“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
这是[编辑:简化]模型(仅包括导致问题的字段)
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)
这是[编辑:简化]覆盖的保存功能。
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']
[编辑]
我从有用的评论中意识到问题出在我的自定义保存功能中,我在其中更新了两个字段。Check 约束失败,因为在某些情况下,我要求为这些 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}
对于“上下文”不在detailed_alts 字典中的实例,我无法保存对实例的更改,因为我已将值设置为np.nan,我猜这在JSONField 中是不允许的。将 np.nan 更改为 'NaN' 解决了这个问题。
至于这是如何解决的,我只需要尝试注释掉保存功能的部分内容,直到找到导致保存失败的部分。然后我测试了保存功能中的每一行,但在尝试保存之前从未出错。因此,不知何故,我突然意识到问题可能出在 jsonfield 上,因为我之前在序列化日期时遇到过问题。