代码之家  ›  专栏  ›  技术社区  ›  Paul McMillan

django unique_,将对象标记为“已删除”

  •  3
  • Paul McMillan  · 技术社区  · 15 年前

    我正在实施中讨论的第一个选项 "Marking for deletion in Django" 也就是说,当一个对象不再处于活动状态时,我设置了一个布尔值将其标记为非活动状态。

    我使用此方法的具体原因是,尽管对象不再处于活动使用状态,但它仍然可以在各种记录和报告输出中引用和显示。我不想让Django的Ripple删除旧记录。

    如何执行活动对象的唯一性?

    最初,我认为我应该使用 unique_together 在数据库级别强制我的约束。直到我删除一个对象,这时添加一个具有相同名称的新活动对象违反了唯一性要求,这才可以正常工作。我可以简单地将对象重新标记为活动对象,但实际上我需要一个新对象。

    我在找一些能让我说“当活动时独特在一起=真”的东西。我可以在模型创建代码中实现这一点,但在数据库级别实现这一点似乎是一个更好的主意。

    关于哪一种方法是最好的,有什么建议吗?有更好的建议吗?

    注意:Django恢复很酷,但完全不适用于我的应用程序,因为我需要不时访问“已删除”的对象。

    3 回复  |  直到 15 年前
        1
  •  4
  •   Matthew Schinckel    15 年前

    您可以有一个唯一的约束:

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

    但是,这意味着您只能有一个活动对象和一个同名的非活动对象。

    如果将active设为nullbooleanfield,则可以将null设为active,并且(iirc)具有无限数量的同名非活动对象。PostgreSQL至少将空值解释为约束的一部分,而不是破坏约束。

        2
  •  0
  •   Nick Presta    15 年前

    我想我知道你这么说是从哪里来的 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执行查询,并访问活动和非活动模型。

        3
  •  0
  •   Mike Fogel    12 年前

    设置如下结构:

    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()
    

    若要删除某个项,请创建一个指向原始项的删除项。将“唯一字段”值复制到删除项。然后将item.unique_字段设置为空。

    这对Postgres和sqlite有效,因为它们 allow NULL's in unique fields . 不能代表其他数据库。