Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BaseChildFormSet doesn't caught IntegrityError for unique together using UniqueConstraint #189

Open
giodiasdev opened this issue Jul 24, 2024 · 0 comments

Comments

@giodiasdev
Copy link

Issue Description

Problem Statement

When attempting to save a Parent instance using BaseChildFormSet, an integrity error occurs if there are two or more Child instances with the same name and parent. This issue specifically arises when utilizing a UniqueConstraint in the Child model, and does not occur when using unique_together.

Context

The models involved are structured as follows:

class Parent(ClusterableModel):
    panels = [
        InlinePanel('children'),
    ]

class Child(models.Model):
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['parent', 'name'], name='unique_name_per_parent')
        ]
    
    parent = ParentalKey(Parent, on_delete=models.CASCADE, related_name='children')
    name = models.CharField(max_length=255)

Issue Specifics

The integrity error manifests when attempting to save a Parent instance through BaseChildFormSet, and involves Child instances sharing the same name and parent combination. This problem is observed exclusively with the use of UniqueConstraint.

Expected Outcome

The form should display a validation error when trying to create or update multiple Child instances that violate the UniqueConstraint. This validation error ensures that users are notified of the uniqueness requirement and prevents the creation of conflicting data.

Proposed Solution

I belive that this issue can be solved adjusting the validate_unique method in the BaseChildFormSet . By ensuring that include_meta_constraints=True is used when retrieving unique checks, the formset will incorporate all applicable constraints, including those defined at the meta-level (e.g., UniqueConstraint).

Code Adjustment

def validate_unique(self):
    '''This clean method will check for unique_together condition'''
    # Collect unique_checks and to run from all the forms.
    all_unique_checks = set()
    all_date_checks = set()
    forms_to_delete = self.deleted_forms
    valid_forms = [form for form in self.forms if form.is_valid() and form not in forms_to_delete]
    for form in valid_forms:
        unique_checks, date_checks = form.instance._get_unique_checks(include_meta_constraints=True)
        all_unique_checks.update(unique_checks)
        all_date_checks.update(date_checks)
@giodiasdev giodiasdev changed the title BaseChildFormSet doesn't caught IntegrityError for unique toguether using UniqueConstraint BaseChildFormSet doesn't caught IntegrityError for unique together using UniqueConstraint Jul 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant