I am using django 3. sqlite database. I have a situation in which an an instance in one of my models will not save. I get an integrity error and "CHECK constraint failed", followed by the name of my model ("post" in my "press" app: press_post). I have looked this up, and i guess it means that a value for one of my fields is impossible? If someone can explain what it means more accurately and precisely, it would be helpful. Mostly, I want to know how to find out which check constraint failed so I can fix it (which field or which piece of data in the model is causing the problem). other instances in the model save without any issues, while a few others have the same problem as this instance.
I can access the instance in shell_plus and look at the data. it looks ok ... but obviously i'm missing something.
the error output:
---------------------------------------------------------------------------
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
here is the [edit: simplified] model (just including the field that caused the problem)
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)
here is the [edit: simplified] overridden save function.
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']
[EDIT]
I realized from the helpful comment that the issue was in my custom save function in which i updated two fields. The Check constraint failed because for some instances I was asking to set something to these JSONFields that was not allowed: a nan value using numpy (np.nan)
here is the relevant (offensive) part of the code: the get_alts method for my model.
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}
for instances in which 'context' was not in the detailed_alts dictionary, i could not save the changes to the instance because i had set the value to np.nan, which I guess isn't allowed in a JSONField. Changing np.nan to 'NaN' fixed the problem.
As far as how this was figured out, i just had to try commenting out parts of the save function until I hit on the parts that caused save to fail. Then I tested each line in the save function, but never got errors until it tried to save it. So, it somehow dawned on me the problem might be the jsonfield because i had problems once before when serializing dates.