Yeah, I was expecting that the validation stops all the processing when saving bin, does it not? Anyways, I copied the same clean method to the BinsHistory model, still happening as long as I try to save two overlapping ranges. I think that triggering on bin_history_overlap constrain was a red herring caused by me trying without the transaction.atomic decorator, which allowed partial saving of the bins model. I can cause the same error as before if I try a combination that isn’t partially saved:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/documents/create
Django Version: 3.2.12
Python Version: 3.9.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'formtools',
'manager']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
The above exception (conflicting key value violates exclusion constraint "bin_ranges_overlap"
DETAIL: Key (document_type, series, serial_range)=(1, 3, [1,101)) conflicts with existing key (document_type, series, serial_range)=(1, 3, [50,301)).
) was the direct cause of the following exception:
File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/home/braiam/src/cert_mng/manager/views.py", line 213, in post
transaction_instance, bins = self.handle_forms(
File "/home/braiam/src/cert_mng/manager/views.py", line 195, in handle_forms
bin_instance.save()
File "/home/braiam/src/cert_mng/manager/models.py", line 380, in save
super().save(*args, **kwargs)
File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 739, in save
self.save_base(using=using, force_insert=force_insert,
File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 776, in save_base
updated = self._save_table(
File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 881, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 919, in _do_insert
return manager._insert(
File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 1270, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/usr/lib/python3/dist-packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
cursor.execute(sql, params)
File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/usr/lib/python3/dist-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/lib/python3/dist-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
Exception Type: IntegrityError at /documents/create
Exception Value: conflicting key value violates exclusion constraint "bin_ranges_overlap"
DETAIL: Key (document_type, series, serial_range)=(1, 3, [1,101)) conflicts with existing key (document_type, series, serial_range)=(1, 3, [50,301)).
It works fine if I’m not saving multiple models at the same time which violate the constrains between themselves. Example (1, 4, [500, 3000]) and (1, 4, [1, 100]) already exist, and if I try to insert them it informs me. But if instead I try (1, 4, [1, 100]) and (1, 4, [50, 300]), I hit the integrity error.