Мягкое удаление с уникальным ограничением в Django - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть модели с таким макетом:

class SafeDeleteModel(models.Model):
    .....
    deleted = models.DateTimeField(editable=False, null=True)
    ......

class MyModel(SafeDeleteModel):
    safedelete_policy = SOFT_DELETE

    field1 = models.CharField(max_length=200)
    field2 = models.CharField(max_length=200)
    field3 = models.ForeignKey(MyModel3)
    field4 = models.ForeignKey(MyModel4)
    field5 = models.ForeignKey(MyModel5)

    class Meta:
        unique_together = [['field2', 'field3', 'field4', 'deleted'],]

Сценарий здесь таков, что я никогда не хочу, чтобы пользователи удаляли данные.Вместо этого удаление будет просто скрывать записи.Тем не менее, я все еще хочу, чтобы все записи без удаленного программного обеспечения соответствовали ограничениям уникального ключа.По сути, я хочу иметь как можно больше дублированных удаленных записей, но может существовать только одна уникальная не удаленная запись.Поэтому я подумал включить «удаленное» поле (предоставленное библиотекой django-safedelete), но проблема заключается в том, что уникальные проверки Django не выполняются с «psycopg2.IntegrityError: значение дублированного ключа нарушает уникальное ограничение» для ['field2', 'field3', 'field4', 'удалено'], потому что NULL не равно NULL и выдает false в PostgreSQL.

Есть ли способ применить ограничение unique_together с макетом модели Django, как у меня?Или есть идея лучше физически удалить запись, затем переместить ее в базу данных архива, и если пользователь захочет вернуть запись обратно, тогда программное обеспечение будет искать запись в архиве и воссоздавать ее?

1 Ответ

0 голосов
/ 27 сентября 2019

Да, начиная с Django версии 2.2 можно использовать UniqueConstraint с условием.

Просмотрите документацию по этой ссылке: https://docs.djangoproject.com/en/2.2/ref/models/constraints/#uniqueconstraint

Таким образом, ваша модель будетбыть примерно таким:

class MyModel(SafeDeleteModel):
    safedelete_policy = SOFT_DELETE

    field1 = models.CharField(max_length=200)
    field2 = models.CharField(max_length=200)
    field3 = models.ForeignKey(MyModel3)
    field4 = models.ForeignKey(MyModel4)
    field5 = models.ForeignKey(MyModel5)

    class Meta:
        constraints = [
            UniqueConstraint(fields=['field2', 'field3', 'field4'], condition=Q(deleted=False), name='unique_if_not_deleted')
        ]

Если вы используете более старую версию Django, у которой нет этой функции, вы можете создать миграцию с частичным уникальным индексом (посмотрите на этот вопрос здесь: Postgresql: Условно-уникальное ограничение ).

Что касается вашего второго вопроса (было бы лучше физически удалить запись и переместить ее в другое место), она действительно зависит от характеристик вашего приложения.,Если эти программные удаления происходят не очень часто, а ваша таблица все еще мала, я бы для простоты сохранил записи в этой же таблице, но если число записей в таблице начинает быстро расти и они влияют наВыполнение запросов в этой таблице, то вы должны переместить записи в другом месте.Вы должны оценить компромисс между сложностью и производительностью.

...