8

在 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

但是,这存在一个问题,即它正在存储没有更改的增量(例如,当title没有更改并且该body字段只有一个增量时。也就是说,当多个字段更改时,它适合 '1 revision == 1 complete修订'。

可能性 2

class PostRevision(models.Model):
    post = ForeignKey(Post)
    field = CharField #Field name
    delta = TextField

通过两种不同的方法,这成功地为我提供了该领域的差异历史,我将使用diff-match-patch生成它(比内置的difflib性能略高)。我现在遇到的两个问题与主对象的生成有关(即链中的最高修订版)。

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

4

2 回答 2

10

我同意@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

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

Image被锁定到 Post,所以事情保持整洁。您可以选择在 Post.save() 函数中清理图像,但我可能会选择 post_save 信号以保持代码更清洁。

于 2013-01-11T16:48:03.697 回答
1

我认为你应该坚持选项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()
于 2013-01-11T12:11:26.213 回答