Python Django中的模型历史

Python Django中的模型历史,python,django,django-models,version,revision-history,Python,Django,Django Models,Version,Revision History,在Django中,如何处理与Post对象关联的图像的并发更改? 这是一个以前被问过的问题,但不完全涵盖相同的问题。我已经通读了这些(、、和),但问题略有不同 我有一个博客文章模型(速度的伪代码),它包含标题、摘要和正文以及相关的图片 class Post(models.Model): title = CharField abstract = TextField body = TextField class Image(models.Model): post =

在Django中,如何处理与Post对象关联的图像的并发更改?

这是一个以前被问过的问题,但不完全涵盖相同的问题。我已经通读了这些(、、和),但问题略有不同

我有一个博客文章模型(速度的伪代码),它包含标题、摘要和正文以及相关的图片

class Post(models.Model):
    title = CharField
    abstract = TextField
    body = TextField

class Image(models.Model):
    post = ForeignKey(Post)
    imagefile = ImageField
现在,我想添加的是存储此
Post
模型更改的历史记录的功能。我想到了两种可能性:

可能性1

class PostHistory(models.Model):
    post = ForeignKey(Post)
    title_delta = TextField
    abstract_delta = TextField
    body_delta = TextField
但是,这有一个问题,即它存储的增量没有变化(例如,
标题
没有变化,并且
正文
字段只有一个增量。也就是说,当多个字段发生变化时,它适合“1个修订==1个完整修订”

可能性2

class PostRevision(models.Model):
    post = ForeignKey(Post)
    field = CharField #Field name
    delta = TextField
通过两种不同的方法,这成功地为我提供了该字段的差异历史记录,我将使用它生成(性能略高于内置)。我现在遇到的两个问题与主对象的生成有关(即链中的顶部修订)


所提出的问题是:如何处理与Post对象关联的图像的并发更改?这些更改将通过
Post
模型的
正文
字段中的引用进行更改(这是一个标记格式的文本字段,然后在表单的
POST
上进行编辑,以添加图像字段的URL引用)。处理此问题的最佳方法是在修订版和
Post
对象上使用M2M字段,允许图像始终与
PostRevision
对象一起存储?

我认为您应该坚持选项1。

一个想法是建立一个自动修订系统。 下面是我将如何做和介意一些语法错误,我键入了我的脑袋

class A(models.Model):
    field1 = ...
    field2 = ...

    def save():
        if bla_bla_updated:
            A_revisions.objects.create(
                         field1=self.fields1, field2=self.fields2,
                         a=self)
        super(A, self).save()

class A_revision(models.Model):
    field1 = ...
    field2 = ...
    a = models.ForeignKey(A)
    revision = models.IntegerField()

    def save():
        self.revision = (A_revision.objects.get(a=self.a)
                                    .order_by('id').revision) + 1
        super(A_revision, self).save()

我同意@rickard zachrisson的观点,你应该坚持方法1。不过我会做一些细微的改变(顺便说一句伪代码):

您的最新版本将始终在
Post
中,并且您的更改历史记录在
pk
中的顺序在
PostHistory
中,这很容易区分更改。我会复制数据,因为存储成本很低,而存储增量是一个pita。如果您进行了多次编辑或希望将当前版本与原始版本进行比较Delta基本上是无用的。AbstractPost中的任何模型更改都会反映在
Post
PostHistory


图像
已设置为Post键,因此内容保持整洁。您可以选择清理帖子中的图像。保存()函数,但我可能会选择一个post_保存信号,以保持代码更干净。

我读得不好或理解错误,但您是否希望保存每个字段修订版或对象作为一个整体?嗯,这是进退两难的一部分,我是否每次都保存整个对象的差异(可能性1)(对于许多字段而言,这基本上是“零更改”,或者为更改的单个字段保存差异(可能性2)?如果一个版本的标题与另一个版本的标题相同,那是不是很糟糕?不,这是一个完全可以接受的情况。假设我选择可能性1,那么这就清除了匹配增量、字段和对象的问题,并保持其原子性-一个版本就是一个版本。后续问题(绑定图像字段),我可能会用图像和修订对象之间的M2Ms来解决这个问题,这听起来合理吗?有一个应用程序可以做到这一点:感谢上面提到的——关于复制数据而不是差异,当文本可能有几千字长,并且一些更改可能小到更改一个完整的sto时,您还会这么说吗p到逗号?我不会预先优化,直到您有更多的数据或存储空间是一个问题(也许压缩数据然后)。这取决于您将版本与另一个版本进行比较的频率。如果您的差异跟踪从一个版本到下一个版本的变化,那么您就有相当多的数据需要读取/处理,只是为了比较两个版本。如果您只存储原始版本的差异,那么随着差异的增大,您会损失更多的存储空间。这是一种折衷方法。
super(Post,self).save()
将不会返回
Post
实例。
class AbstractPost(models.Model):
    title = CharField
    abstract = TextField
    body = TextField

    class Meta:
        abstract = True


class Post(AbstractPost):
    def save(self):
        post = super(Post, self).save()

        PostHistory.objects.create(
            post=post,
            title=post.title,
            abstract=post.abstract,
            body=post.body,
        )


class PostHistory(AbstractPost):
    post = ForeignKey(Post)

    class Meta:
        ordering = ['-pk']


class Image(models.Model):
    post = ForeignKey(Post)
    imagefile = ImageField