Django中的模型历史

jvc*_*c26 5 python django version django-models revision-history

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

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

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

class Image(models.Model):
    post = ForeignKey(Post)
    imagefile = ImageField
Run Code Online (Sandbox Code Playgroud)

现在,我想要添加的是能够存储此Post模型的更改历史记录.我想到了两种可能性:

可能性1

class PostHistory(models.Model):
    post = ForeignKey(Post)
    title_delta = TextField
    abstract_delta = TextField
    body_delta = TextField
Run Code Online (Sandbox Code Playgroud)

然而,这有一个问题,即它存储增量没有变化(例如,当title没有变化时,body字段只有一个增量.也就是说,当多个字段发生变化时,它符合'1版本== 1完成修订版".

可能性2

class PostRevision(models.Model):
    post = ForeignKey(Post)
    field = CharField #Field name
    delta = TextField
Run Code Online (Sandbox Code Playgroud)

通过两种不同的方法,这成功地给了我一个场的差异历史,我将使用diff-match-patch生成(比内置的difflib稍微高一些).我现在遇到的两个问题与主对象的生成有关(即链中的最高版本).

问题是,我如何处理与Post对象关联的图像的并发更改,因为这些将通过模型body字段内的引用进行更改Post(这是Markdown格式化的文本字段,然后进行编辑POST)要添加到图像字段的URL引用中的表单.处理此问题的最佳方法是在修订版本和Post对象上使用M2M字段,从而允许图像始终与PostRevision对象一起存储吗?

小智 8

我同意@ rickard-zachrisson你应该坚持方法#1.我做了一些微妙的改动(伪代码顺便说一句):

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
Run Code Online (Sandbox Code Playgroud)

您的最新版本将始终存在Post,您的更改历史记录将按pk顺序PostHistory进行更改.我会复制数据,因为存储很便宜并且存储增量是一个皮塔饼.如果您有多个编辑或想要将当前版本与原始版本进行比较,那么增量基本上是无用的.AbstractPost中的任何模型更改都反映在PostPostHistory.

Image是关键的邮政所以事情保持整洁.您可以选择清理Post.save()函数中的图像,但我可能会选择post_save信号来保持代码清洁.

  • `super(Post, self).save()` 不会返回 `post` 实例。 (2认同)