﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
35550	UniqueConstraint with condition seems not checked in BaseInlineFormSet	Serl	nobody	"Hello,
I spotted a corner case for which we have an `IntegrityError` instead of a `ValidationError`.

I've put together a [https://github.com/serl/django-fieldset-unique-bug demo project with all the details], the most important follows.

I have a model like so:

{{{
class Product(models.Model):
    design = models.ForeignKey(...)
    type = models.CharField(...)
    size = models.CharField(null=True, ...)
    ...

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[""design"", ""type""],
                condition=models.Q(size__isnull=True),
                name=""unique_design_type"",
            ),
            ...
        ]
}}}

I'm using the standard forms in the admin site.

If I try to violate that `UniqueConstraint` from `ProductAdmin`, I correctly get a validation error. I materialized this check in a test case `TestFormValidation.test_validation_unique_design_type`.

If I try to violate it from the formset in `ProductInlineAdmin` in `DesignAdmin`, I get a 500 error. The test case `TestFormSetValidation.test_validation_unique_design_type` shows the expected and actual behavior:

{{{
def test_validation_unique_design_type(self):
    ...

    formset = FormSet(
        data={
            f""{prefix}-INITIAL_FORMS"": ""0"",
            f""{prefix}-TOTAL_FORMS"": ""2"",
            f""{prefix}-MAX_NUM_FORMS"": ""1000"",
            f""{prefix}-0-type"": ""Mug"",
            f""{prefix}-0-price"": ""2"",
            f""{prefix}-1-type"": ""Mug"",
            f""{prefix}-1-price"": ""2"",
        },
        instance=self.design,
    )

    # EXPECTED BEHAVIOR
    self.assertFalse(formset.is_valid())
    with self.assertRaisesMessage(ValueError, ""didn't validate""):
        formset.save()

    # ACTUAL BEHAVIOR
    self.assertTrue(formset.is_valid())
    with self.assertRaisesMessage(IntegrityError, ""UNIQUE constraint failed""):
        formset.save()
}}}

''Note that in the demo project I also added a second `UniqueConstraint` with three fields and no condition, and that works like a charm (test cases there to prove). That second constraint actually show the pattern that I use in the main project, which is to have an unique constraint on three fields, one of which is nullable - that is `nulls_distinct=False` before updating to Django 5 and Postgres 15. But I digress.''

As a workaround for may day job I implemented a custom `clean` in my inline formsets.

If you agree on the buggy nature of this behavior, I'd like to participate with a PR. Let me know your thoughts."	Bug	closed	Forms	5.0	Normal	duplicate			Unreviewed	0	0	0	0	0	0
