django - 如何在不覆盖原始条目的情况下保存修改后的表单

时间:2016-02-29 15:54:49

标签: python django django-models

我有一个合乎逻辑的"如何"或最佳实践问题。

简化示例

我有一个带文本框的模型类。用户可以添加新条目,但只有管理员接受它们才会显示给其他用户。

class MyClass(models.Model):
    # Relation to a user
    user = ForeignKey(User)
    # Simple textbox as example attribute
    text = TextArea()
    # Admin has to accept the entry that other users can see it
    accepted = BooleanField(default=False)

问题

我想让用户修改一个列表,但管理员必须先接受它们。只要管理员不接受修改,它仍应显示该条目的旧的未修改版本。

我的方法

a)创建一个新类

class MyEditClass(models.Model)
    # ForeignKey to the original class
    fk = ForeignKey(MyClass)
    user = ForeignKey(User)
    text = TextArea()
    accepted = BooleanField(default=False)

修改将保存在新的表/类中。如果管理员接受此修改后的条目,则原始条目将成为此条目。

为什么我不喜欢它?我的班级有大约60个具有很多关系的属性。由于我还没有找到复制完整类的解决方案,因此产生了大量重复的代码行。如果我添加一个新的attr。在MyClass我还必须在MyEditClass ...

中添加它

b)如果条目已被修改,请向MyClass添加新的属性

class MyClass(models.Model):
    # new attribute with the primary key of the edited field
    edited_pk = PositiveIntegerField(default=None, blank=True, none=True)
    user = ForeignKey(User)
    text = TextArea()
    accepted = BooleanField(default=False)

在这种情况下,您不会创建新类,而是将已编辑的条目保存在同一个类中,并添加属性edited_pk。如果条目是新条目集edited_pk = None(默认值)。如果用户修改条目,则从原始条目获取pk。然后将修改后的一个添加为edited_pk = original_entry.pk的新条目。如果管理员接受修改后的版本,则原始条目将被修改后的条目覆盖。

为什么我不喜欢这个解决方案?作为管理员,我希望在后端有一个类来接受修改后的条目。

你有其他(可能已经是bultin或第三方)的方法吗?

提前致谢

(标题不好,但我找不到更好的名字。如果你这样做,请编辑)

解决方案

如果您不想使用第三方应用,请检查标记的答案。

我最喜欢的解决方案,也是 Obj3ctiv3_C_88 需要django-simple-history。 因此我创建了一个方法:

class MyClass(models.Model):
    user = ForeignKey(User)
    text = TextArea()
    accepted = BooleanField(default=False)
    history = HistoricalRecords()  # rtd from django-simple-history

    def get_accepted(self):
        """Return the first entry from the history which is accepted."""
        return self.history.filter(accepted=True).first()

在您的观点中:

# This code may be optimized, but for now it works
items = MyClass.objects.all()
items = list(items)  # convert queryset to a list
i = 0
for item in items:
    # Important to get the instance. Otherwise custom methods won't work
    items[i] = item.get_accepted().instance
    i += 1

1 个答案:

答案 0 :(得分:1)

这样的事情会起作用吗?

class BlogComment(models.Model):
    blog = models.ForeignKey(Blog)
    user = models.ForeignKey(User)
    unapproved = models.Charfield(max_length=1000, default=None, Blank=True)
    approved = models.Charfield(max_length=1000, default=None, Blank=True)

# on submit
BlogComment.unapproved = request.POST['user_comment']

# on approve
BlogComment.approved = BlogComment.unapproved
BlogComment.unapproved = None
BlogComment.save()

这将允许您为同一评论保留2个不同的状态。您只渲染BlogComment.approved。要查找需要批准的注释,您只需过滤(~Q(未批准=无))