#35374: UniqueConstraint (and potentially other constraints) validation is not 
run
when using a form generated from `inlineformset_factory`
--------------------------------------+------------------------
               Reporter:  David Hang  |          Owner:  nobody
                   Type:  Bug         |         Status:  new
              Component:  Forms       |        Version:  4.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           |
--------------------------------------+------------------------
 Due to how refactors in Django 4+ on how the unique validations are run
 for models and forms, an edge case has occured where in an inline form,
 `UniqueConstraint` checks which were previously run are now being skipped
 over and not returning validation errors, which then causing database
 integrity errors when the form is attempted to be saved.

 Reproducible example:


 {{{
 from django.forms import inlineformset_factory
 from django import forms
 from django.db import models


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


 class Apple(models.Model):
     name = models.CharField(max_length=255)
     farm = models.ForeignKey(Farm, on_delete=models.CASCADE)

     class Meta:
         constraints = [
             models.UniqueConstraint(fields=["name", "farm"],
 name="unique_apple")
         ]


 class AppleForm(forms.ModelForm):
     class Meta:
         model = Apple

         fields = ["name", "farm"]


 big_farm = Farm.objects.create(name="Big Farm")
 best_apple = Apple.objects.create(name="Best Apple", farm=big_farm)

 AppleFormSet = inlineformset_factory(Farm, Apple, AppleForm)

 data = {
     "apple_set-TOTAL_FORMS": "2",
     "apple_set-INITIAL_FORMS": "0",
     "apple_set-0-name": "Best Apple",
     "apple_set-0-farm": big_farm.pk,
 }

 formset = AppleFormSet(data, instance=big_farm)

 print(formset.is_valid())
 print(formset.errors)

 formset.save()

 }}}


 {{{
 IntegrityError: duplicate key value violates unique constraint
 "unique_apple"
 DETAIL:  Key (name, farm_id)=(Best Apple, 3) already exists.
 }}}

 In normal forms, and formsets, the validation does run correctly. This
 issue caused by
 
https://github.com/django/django/blob/42bc81b1b6471c4fe364bc32b9dec180908e577e/django/forms/models.py#L486


 {{{

         # Foreign Keys being used to represent inline relationships
         # are excluded from basic field value validation. This is for two
         # reasons: firstly, the value may not be supplied (#12507; the
         # case of providing new values to the admin); secondly the
         # object being referred to may not yet fully exist (#12749).
         # However, these fields *must* be included in uniqueness checks,
         # so this can't be part of _get_validation_exclusions().
         for name, field in self.fields.items():
             if isinstance(field, InlineForeignKeyField):
                 exclude.add(name)
 }}}
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35374>
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/0107018ee010d578-174a675f-4802-4457-9c7d-25d87659e311-000000%40eu-central-1.amazonses.com.

Reply via email to