'Django: How to enforce UniqueConstraint with parent and child models

Say I have the following models:

class ParentModel(models.Model):
    parent_field_1 = models.CharField(max_length=10)
    parent_field_2 = models.CharField(max_length=10)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['parent_field_1', 'parent_field_2', 'child_field_2'],
                name='unique_parent_example'
            )
        ] 

class ChildModel(ParentModel):
    child_field_1 = models.CharField(max_length=10)
    child_field_2 = models.CharField(max_length=10)

I want to utilise the ParentModel's UniqueConstraint but apply an additional field within the ChildModel's UniqueConstraint. I know this is not possible but to help visualise the idea, I'd ideally like to do something like this:

class ChildModel(ParentModel):
    [.. fields ..]

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['parentmodel', 'child_field_2'],
                name='unique_child_example'
            )
        ] 

Almost like I'm building the unique constraint as inheritance also.

How could I do this?



Solution 1:[1]

Multi-table inheritance (as you are using) uses a one to one relationship. this means that every parent can have only one child and vice versa

this would implicitly bring into effect the unique-ness of children as they can only relate to one parent, so if the parent is unique, so will the child.

in order to prevent duplicated information in the child model just apply meta constraints as in the parent or do unique=True in the fields

If you want only some of the columns in the child to be unique to the parent - then as you said - this is not possible. To achieve something like that you would need to split the child into multiple models - the unique stuff would remain in the child that inherited from the parent while the other stuff would be in another model that had a foreign key relationship to the parent

here is what I would do based on what you shared:

class ParentModel(models.Model):
    parent_field_1 = models.CharField(max_length=10)
    parent_field_2 = models.CharField(max_length=10)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['parent_field_1', 'parent_field_2'],
                name='unique_parent'
            )
        ] 

class ChildModel(ParentModel):
    child_field_2 = models.CharField(max_length=10, unique=true)
    # this being unique means that only one parent can have a child like this 


class UnInheritedChild(models.Model):
    child_field_1 = models.CharField(max_length=10)
    parent = models.ForeignKey(ParentModel, on_delete=models.CASCADE)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dafrandle