#35676: ExclusionConstraint that includes a ForeignKey fails validation in
ModelForm
-----------------------------+-----------------------------------------
     Reporter:  diesieben07  |                     Type:  Uncategorized
       Status:  new          |                Component:  Uncategorized
      Version:  5.1          |                 Severity:  Normal
     Keywords:               |             Triage Stage:  Unreviewed
    Has patch:  0            |      Needs documentation:  0
  Needs tests:  0            |  Patch needs improvement:  0
Easy pickings:  0            |                    UI/UX:  0
-----------------------------+-----------------------------------------
 I'm not sure if the summary above is good, but let me demonstrate:

 {{{
 class BlockedDaysConfig(models.Model):
     name = models.CharField(max_length=255)


 class BlockedDaysRange(models.Model):
     config = models.ForeignKey(BlockedDaysConfig,
 on_delete=models.CASCADE, related_name='days')
     date_range = DateRangeField()

     class Meta:
         constraints = (
             ExclusionConstraint(
 name='%(app_label)s_%(class)s_no_overlapping_ranges_per_config',
                 expressions=(
                     ('config_id', RangeOperators.EQUAL, ),
                     ('date_range', RangeOperators.OVERLAPS, ),
                 )
             ),
         )
 }}}

 `BlockedDaysRange` represents a range of blocked days. `BlockedDaysConfig`
 represents a range of these blocked days. Example:
 A BlockedDaysConfig with name "School Holidays in Germany" contains
 several BlockedDaysConfig entries, one for "summer holidays", one for
 "winter holidays", etc.
 The exclusion constraint validates that the date ranges within one config
 do not overlap.

 Now I have configured a ModelAdmin for this:

 {{{
 class BlockedDaysRangeInline(admin.TabularInline):
     model = BlockedDaysRange


 @admin.register(BlockedDaysConfig)
 class BlockedDaysConfigAdmin(admin.ModelAdmin):
     inlines = (BlockedDaysRangeInline, )
 }}}

 The problem now happens when saving, because `BaseModelForm._post_clean`
 will ''exclude'' the `InlineForeignKey` for `config` when calling
 `full_clean` (see
 
https://github.com/django/django/blob/b99c608ea10cabc97a6b251cdb6e81ef2a83bdcf/django/forms/models.py#L477-L488).
 Because `config` is in `exclude`, when `ExclusionConstraint` eventually
 calls `_get_field_value_map`, the `config` is not included and thus a
 nonsensical SQL query happens (`WHERE config_id=config_id and date_range
 && '[2024-01-01,2024-01-03)'::daterange`). This will now validate against
 ''any'' date ranges, not just ones with the same `config_id`.
 As you can see from the comment in the code snippet linked above, this
 problem is already recognized for unique constraints, which are handled
 specially by `ModelForm`.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35676>
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/010701914c624924-03d7e5a1-19f4-4888-a575-645070c37a5f-000000%40eu-central-1.amazonses.com.

Reply via email to