#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 django-updates+unsubscr...@googlegroups.com.
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