8

Djangoでは、Postオブジェクトに関連付けられた画像への同時変更をどのように処理しますか?

これは以前に尋ねられた質問の傾向ですが、同じ問題を完全にはカバーしていません。これら ( questionquestionquestion、およびquestion ) を読みましたが、問題は少し異なります。

タイトル、要約、本文、および関連する画像を含むブログ投稿モデル (速度のための擬似コード) があります。

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

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

ここで追加したいのは、このPostモデルへの変更履歴を保存する機能です。これについては、次の 2 つの可能性を考えました。

可能性 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

2 つの異なるアプローチにより、これはフィールドの diff の履歴を正常に取得します。これは、 diff-match-patchを使用して生成します (組み込みのdifflibよりもわずかにパフォーマンスが優れています)。私が現在抱えている 2 つの問題は、マスター オブジェクトの生成 (つまり、チェーンの最上位のリビジョン) に関連しています。

問題は、投稿オブジェクトに関連付けられた画像への同時変更をどのように処理するかということです。これらはbody、モデルのフィールド内の参照を介して変更されます (これは、画像フィールドの URL 参照を追加するためにフォームPost上で編集される Markdown 形式のテキスト フィールドです)。POSTこれに対処する最善の方法は、リビジョンとPostオブジェクトで M2M フィールドを使用して、画像を常に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でのモデルの変更は、との両方に反映されPostますPostHistory

Image投稿に対応しているので、物事は整頓されています。オプションで、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 に答える