0

これは、Stackoverflow に似た、共同モデレーションの機能を有効にするアプリケーションに関するものです。

現在の状態

次のような Django ORM クエリがあります。

versions = Version.objects.filter(is_reviewed=False).exclude(moderations__user__pk=request.user.id).order_by('content_type__id', 'object_id', '-number').distinct('content_type', 'object_id')

各コンテンツ オブジェクトは、ユーザーが作成した任意の数のバージョンを持つことができます。ここで行っているのは、他のユーザーからのすべてのレビューされていないバージョンを取得することですが、コンテンツ オブジェクトごとに最新のバージョンのみを取得します。

問題

しかし、別の除外条件を追加したい: コンテンツ オブジェクトに新しいバージョンがある場合is_reviewed=True、以前のバージョンを返すべきではありません。ただし、レビューされていない新しいものは返却する必要があります。これを行う方法はありますか?

いくつかの例。ここにあるすべてのバージョンが同じコンテンツ オブジェクト用であると想定しています。

例A

  1. 「最初のバージョン」 - 未レビュー
  2. 「改良版」 - 未レビュー
  3. 「さらに改良されたバージョン」 - 未レビュー

これにより、3 行目が返されます。期待どおりに動作します。

例 B

  1. 「最初のバージョン」 -レビュー
  2. 「改良版」 - 未レビュー
  3. 「さらに改良されたバージョン」 - 未レビュー

これにより、3 行目が返されます。期待どおりに動作します。

例 C

  1. 「最初のバージョン」 - 未レビュー
  2. 「改良版」 -レビュー
  3. 「さらに改良されたバージョン」 - 未レビュー

これにより、3 行目が返されます。期待どおりに動作します。

例 D

  1. 「最初のバージョン」 - 未レビュー
  2. 「改良版」 - 未レビュー
  3. 「さらに改良されたバージョン」 -レビュー

これはno rowを返すはずです。これは現時点では機能しません。意図したものではない2行目を返します。

/編集

ここに私のモデルがあります: http://sql.nopaste.dk/p48981

4

1 に答える 1

1

私は、何をしようとしているのかを説明するのに役立つクエリセット メソッドを記述し、そこから逆方向に作業するのが好きです。

Version.objects.newest_by_content_type().unreviewed()

次に、queryset/manager メソッドだけが必要です。[注:高レベルのクエリ API の構築で説明されているパターンを使用して、これらのメソッドをクエリ セットに追加しています]。

結局のところ、これはあなたが既に書いたコードで、順序がわずかに異なっているだけです。

def newest_by_content_type(self):
    return self.order_by('content_type__id', 'object_id', '-updated').distinct('content_type', 'object_id')

def unreviewed(self):
    return self.filter(is_reviewed=False)

次に、このクエリ セットを使用して他のことを行うことができます。たとえば、現在のユーザーが所有するものを削除します。

この回答の前の化身では、superseded_by、またはsupersedes自己関係を使用した代替ソリューションについて説明しました。

class Version(models.Model):
    supersedes = models.ForeignKey('Version', 
        related_name='superseded_by', null=True, blank=True)

次に、次の方法で、置き換えられていないすべてのオブジェクトを取得できます。

Version.objects.filter(superseded_by=None)

制約によってはOneToOneField、置き換えられた関係に a を使用するのが理にかなっている場合があります。バージョンを置き換えることができるのは最大で 1 つのバージョンのみであり、バージョンは 1 つのバージョンのみを置き換えることができる場合です。これを HTTP ヘッダーと一緒に使用して、412 Precondition Failedたとえば、既に置き換えられたオブジェクトを再度置き換えようとしたときに戻ることもできます。これは、バージョン チェーンが「ストレート」であり、ブランチが許可されていない場合に意味があります。

于 2013-06-20T07:25:47.133 に答える