summaryrefslogtreecommitdiff
path: root/postgresqleu/util/backendviews.py
diff options
context:
space:
mode:
authorMagnus Hagander2024-01-21 14:09:31 +0000
committerMagnus Hagander2024-01-21 14:09:31 +0000
commit04d3df3547a2bf04b819590a9cf7a6e7ce6f0919 (patch)
tree8cb800a245674b7d2e54b7dd66e8365e88de41bd /postgresqleu/util/backendviews.py
parent15e0e750d7d4d019cd628b1accf270cf74ed4822 (diff)
Handle database level constraint errors in backend editor
Backend editor would just crash if we failed to save due to a database level constraint (foreign key, unique etc), even if said constraint was defined in django (not for foreign keys as they drive dropdowns, but django does not validate uniqueness, and there could always be a CHECK constraint as well). So trap any such exceptions when trying to save and just show the full error message to the user, instead of crashing.
Diffstat (limited to 'postgresqleu/util/backendviews.py')
-rw-r--r--postgresqleu/util/backendviews.py61
1 files changed, 32 insertions, 29 deletions
diff --git a/postgresqleu/util/backendviews.py b/postgresqleu/util/backendviews.py
index 0ab40dd5..72836633 100644
--- a/postgresqleu/util/backendviews.py
+++ b/postgresqleu/util/backendviews.py
@@ -1,5 +1,5 @@
from django.core.exceptions import PermissionDenied, ValidationError
-from django.db import transaction
+from django.db import transaction, DatabaseError
from django import forms
from django.shortcuts import render, get_object_or_404
from django.urls import reverse, NoReverseMatch
@@ -165,34 +165,37 @@ def backend_process_form(request, urlname, formclass, id, cancel_url='../', save
# fields on the model, including those we don't care about.
# The savem2m model, however, *does* care about the listed fields.
# Consistency is overrated!
- with transaction.atomic():
- if allow_new and ((not instance.pk) or form.force_insert):
- form.pre_create_item()
- form.save()
- form._save_m2m()
- all_excludes = ['_validator', '_newformdata'] + list(form.readonly_fields) + form.nosave_fields
- if form.json_form_fields:
- for fn, ffields in form.json_form_fields.items():
- all_excludes.extend(ffields)
-
- form.instance.save(update_fields=[f for f in form.fields.keys() if f not in all_excludes and not isinstance(form[f].field, forms.ModelMultipleChoiceField)] + form.extra_update_fields)
-
- # Merge fields stored in json
- if form.json_form_fields:
- for fn, ffields in form.json_form_fields.items():
- d = getattr(form.instance, fn, {})
- for fld in ffields:
- if form.cleaned_data[fld] or not getattr(form.fields[fld], 'delete_on_empty', False):
- # If we have a value, or if we're asked to store empty strings,
- # then do so.
- d[fld] = form.cleaned_data[fld]
- elif form.cleaned_data[fld] == '' and getattr(form.fields[fld], 'delete_on_empty', False) and fld in d:
- del d[fld]
- setattr(form.instance, fn, d)
- form.instance.save(update_fields=form.json_form_fields.keys())
-
- form.post_save()
- return HttpResponseRedirect(saved_url)
+ try:
+ with transaction.atomic():
+ if allow_new and ((not instance.pk) or form.force_insert):
+ form.pre_create_item()
+ form.save()
+ form._save_m2m()
+ all_excludes = ['_validator', '_newformdata'] + list(form.readonly_fields) + form.nosave_fields
+ if form.json_form_fields:
+ for fn, ffields in form.json_form_fields.items():
+ all_excludes.extend(ffields)
+
+ form.instance.save(update_fields=[f for f in form.fields.keys() if f not in all_excludes and not isinstance(form[f].field, forms.ModelMultipleChoiceField)] + form.extra_update_fields)
+
+ # Merge fields stored in json
+ if form.json_form_fields:
+ for fn, ffields in form.json_form_fields.items():
+ d = getattr(form.instance, fn, {})
+ for fld in ffields:
+ if form.cleaned_data[fld] or not getattr(form.fields[fld], 'delete_on_empty', False):
+ # If we have a value, or if we're asked to store empty strings,
+ # then do so.
+ d[fld] = form.cleaned_data[fld]
+ elif form.cleaned_data[fld] == '' and getattr(form.fields[fld], 'delete_on_empty', False) and fld in d:
+ del d[fld]
+ setattr(form.instance, fn, d)
+ form.instance.save(update_fields=form.json_form_fields.keys())
+
+ form.post_save()
+ return HttpResponseRedirect(saved_url)
+ except DatabaseError as e:
+ form.add_error(None, "Failed to save entry: {}".format(e))
else:
form = formclass(request, conference, instance=instance, newformdata=newformdata)