这是之前提出过的一个问题,但不完全涵盖同样的问题。我已经仔细阅读了这些内容(question,question,question和question),但问题略有不同。
我有一个博客文章模型(速度伪代码),其中包含标题,摘要和正文以及相关图像。
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修订版== 1完整修订版'。
可能性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
对象一起存储?
答案 0 :(得分: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
您的最新版本将始终位于Post
,并且您的更改历史记录位于pk
的{{1}}顺序,这很容易与更改区分开来。我会复制数据,因为存储很便宜并且存储增量是一个皮塔饼。如果您有多个编辑或想要将当前版本与原始版本进行比较,那么增量基本上是无用的。 AbstractPost中的任何模型更改都会反映在PostHistory
和Post
中。
PostHistory
是关键的帖子,所以事情保持整洁。您可以选择清理Post.save()函数中的图像,但我可能会选择post_save信号来保持代码清洁。
答案 1 :(得分: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()