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

Custom UniqueConstraint do not works with OneToOneField #241

Open
LECARROU opened this issue Apr 17, 2024 · 1 comment
Open

Custom UniqueConstraint do not works with OneToOneField #241

LECARROU opened this issue Apr 17, 2024 · 1 comment

Comments

@LECARROU
Copy link

I use many models with OneToOneField with default unique=True.

I would like the user to be able to create a record in table Exam even if one or more records are marked as soft (logically) deleted and linked to the same record in table Followup.
But when I have a model with OneToOneField, if I deleted a record 1 in table Exam linked to a record 1 in table Followup and I try to recreate a record 2 in table Exam linked to the same record 1 from table Followup, I get an IntegrityError because the uniqueness is not respected.

I read about the possibility of "revive" a deleted object but that's not what I want. I want to have multiple deleted records but only one undeleted one that respects the integrity of the constraints.
I read the section on field uniqueness in the documentation where a unique constraint can be set to exclude deleted records.
I try to implement this UniqueConstraint but it doesn't works.

I try to customize a ModelManager to set _safedelete_visibility = DELETED_VISIBLE_BY_PK but doesn't seems to works.
In my Postgresql database, a soft deleted object is not accessible with Exam.objects.filter(uuid='my-uuid') wherease it is for non soft deleted objects.

class Followup(SafeDeleteModel):
    _safedelete_policy = SOFT_DELETE_CASCADE
    uuid = models.UUIDField(default=uuid.uuid4, max_length=36, null=False, unique=True, primary_key=True)
    date = models.DateField("Date", null=True, blank=True)
    
class Exam(SafeDeleteModel):
    _safedelete_policy = SOFT_DELETE_CASCADE
    uuid = models.UUIDField(default=uuid.uuid4, max_length=36, null=False, unique=True, primary_key=True)
    followup = models.OneToOneField(Followup, null=True, blank=True, on_delete=models.CASCADE, related_name='exam', default=None)
    class Meta:
        constraints = [
            UniqueConstraint(
                fields=['followup'],
                condition=Q(deleted__isnull=True),
                name='unique_active_one_to_one_field'
            ),
        ]
    
@LECARROU
Copy link
Author

A solution seems to change OneToOneField to ForeignKey and define UniqueConstraint in Class Meta as mentionned above.
But As ForeignKey reverse relation return a QuerySet and not a single object, I have to modify all my template to add ".first" to access a single Exam object from Followup object

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