Django unique_together и помечать объекты как «удаленные» - PullRequest
3 голосов
/ 02 ноября 2009

Я реализую первый параметр, описанный в «Маркировка для удаления в Django» , то есть когда объект больше не активен, я устанавливаю логическое значение, чтобы пометить его как неактивный.

Конкретная причина, по которой я использую этот метод, заключается в том, что, хотя объект больше не используется активно, на него все же можно ссылаться и отображать в различных записях и отчетах. Я не хочу, чтобы пульсация Django удаляла старые записи.

Как мне обеспечить уникальность активных объектов?

Изначально я подумал, что должен использовать unique_together для усиления моих ограничений на уровне базы данных. Это работает нормально, пока я не удаляю объект, после чего добавление нового активного объекта с тем же именем нарушает требование уникальности. Я мог бы просто пометить объект как активный, но я действительно хочу новый объект.

Я ищу что-то, что позволило бы мне сказать что-то вроде "уникально вместе, когда активно = Истина". Я мог бы применить это в коде создания модели, но кажется, что применение этого на уровне базы данных - лучшая идея.

Любой совет, какой из них является лучшим подходом? Есть лучшие предложения?

Примечание: django-reversion - это круто, но полностью не работает для моего приложения, так как мне НЕОБХОДИМО время от времени получать доступ к "удаленным" объектам.

Ответы [ 3 ]

4 голосов
/ 02 ноября 2009

У вас может быть уникальное ограничение:

class Meta:
     unique_together = ( ('name', 'active'),)

Однако это означает, что вы можете иметь только один активный и один неактивный объект с одинаковым именем.

Если вы сделаете активным NullBooleanField, тогда вы можете иметь NULL для активного и иметь (IIRC) неограниченное количество неактивных объектов с тем же именем. PostgreSQL, по крайней мере, интерпретирует значение NULL как часть ограничения как не нарушающее ограничение.

0 голосов
/ 16 августа 2012

Настройте структуру следующим образом:

class Item(models.Model):
    unique_field = models.CharField(unique=True, null=True)

class DeletedItem(models.Model):
    original = models.OneToOneField(Item)
    original_unique_field = models.CharField()

Чтобы удалить элемент, был создан элемент DeletedItem, который указывает на исходный элемент. Скопируйте значение «unique_field» в DeletedItem. Затем установите для вашего Item.unique_field значение NULL.

Это работает на Postgres и sqlite, потому что они допускают значения NULL в уникальных полях . Не могу сказать о других БД.

0 голосов
/ 02 ноября 2009

Мне кажется, я понимаю, откуда вы, когда говорите, что unique together должен оставаться на уровне базы данных. В теоретически лучших ситуациях лучшим вариантом будет такой, который не полагается на понимание базового применения БД unique together и вместо этого действует так, как будто это ограничение является постоянным правилом для этой таблицы.

Исходя из этой идеи, что, если различие между активным / неактивным произошло на «уровне таблицы», а не с каким-то необычным взломом модели?

Обратите внимание на следующее:

class BaseModel(models.Model):
    # all of your fields here
    active = models.BooleanField()


class ActiveModel(BaseModel):    
    class Meta:
        unique_together = ('whatever', 'fields')    

    def make_inactive(self):
        # create a new instance of InactiveModel based on
        # this instances's values, then delete this instance


class InactiveModel(BaseModel):
    def make_active(self):
        # create a new instance of InactiveModel based on
        # this instances's values, then delete this instance

Таким образом, всякий раз, когда вы создаете новую модель, вы делаете это с помощью ActiveModel. Затем уникальный_всем применяется только для активных моделей. Чтобы пометить модель как неактивную, вы делаете model.make_inactive вместо прежнего model.active=False. Вы по-прежнему можете выполнять запросы к BaseModel и получать доступ как к активным, так и к неактивным моделям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...