#35676: ExclusionConstraint that includes a ForeignKey fails validation in
ModelForm
------------------------------+------------------------------------
Reporter: Take Weiland | Owner: (none)
Type: Bug | Status: new
Component: Forms | Version: 5.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------
Changes (by Simon Charette):
* component: Uncategorized => Forms
* stage: Unreviewed => Accepted
* type: Uncategorized => Bug
Comment:
Thanks for the detailed report.
[
https://github.com/django/django/blob/b99c608ea10cabc97a6b251cdb6e81ef2a83bdcf/django/forms/models.py#L477-L488
The comment you pointed at] makes it clear that this is a variant of
#12960 but for constraints instead of uniques.
I think something along the following lines should address the issue but
I'm curious to hear your thoughts on it.
{{{#!diff
diff --git a/django/forms/models.py b/django/forms/models.py
index 8084e16c8d..bbb4d94e33 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -370,10 +370,12 @@ def __init__(
# if initial was provided, it should override the values from
instance
if initial is not None:
object_data.update(initial)
- # self._validate_unique will be set to True by
BaseModelForm.clean().
- # It is False by default so overriding self.clean() and failing
to call
- # super will stop validate_unique from being called.
+ # self._validate_(unique|constraints) will be set to True by
+ # BaseModelForm.clean(). It is False by default so overriding
+ # self.clean() and failing to call super will stop
+ # validate_(unique|constraints) from being called.
self._validate_unique = False
+ self._validate_constraints = False
super().__init__(
data,
files,
@@ -436,6 +438,7 @@ def _get_validation_exclusions(self):
def clean(self):
self._validate_unique = True
+ self._validate_constraints = True
return self.cleaned_data
def _update_errors(self, errors):
@@ -495,13 +498,17 @@ def _post_clean(self):
self._update_errors(e)
try:
- self.instance.full_clean(exclude=exclude,
validate_unique=False)
+ self.instance.full_clean(
+ exclude=exclude, validate_unique=False,
validate_constraints=False
+ )
except ValidationError as e:
self._update_errors(e)
- # Validate uniqueness if needed.
+ # Validate uniqueness and constraints if needed.
if self._validate_unique:
self.validate_unique()
+ if self._validate_constraints:
+ self.validate_constraints()
def validate_unique(self):
"""
@@ -514,6 +521,17 @@ def validate_unique(self):
except ValidationError as e:
self._update_errors(e)
+ def validate_constraints(self):
+ """
+ Call the instance's validate_constraints() method and update the
form's
+ validation errors if any were raised.
+ """
+ exclude = self._get_validation_exclusions()
+ try:
+ self.instance.validate_constraints(exclude=exclude)
+ except ValidationError as e:
+ self._update_errors(e)
+
def _save_m2m(self):
"""
Save the many-to-many fields and generic relations for this form.
}}}
--
Ticket URL: <
https://code.djangoproject.com/ticket/35676#comment:1>