#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>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701914c7484d6-fe8fb74f-f5a9-46bd-9841-71910b95366e-000000%40eu-central-1.amazonses.com.

Reply via email to