56

非常に頻繁に次のような構造を目にします

MyModel.objects.all().filter(...)

デフォルトの Mananger の QuerySet を返します。最初all()はかなり冗長に思えます。

MyMode.objects.filter(...)

同じ結果をもたらします。

ただし、Django のドキュメントに次の 2 つのステートメントがあるため、これはデフォルトの Manager に対してのみ安全であるように思われます。

「追加のマネージャ メソッドの追加」の章からの抜粋

カスタム Manager メソッドは、必要なものを何でも返すことができます。QuerySet を返す必要はありません。

all()manager メソッドの定義:

all() 現在の QuerySet (または QuerySet サブクラス) のコピーを返します。これは、モデル マネージャまたは QuerySet のいずれかを渡して、結果をさらにフィルタリングする必要がある場合に役立ちます。いずれかのオブジェクトで all() を呼び出した後は、操作する QuerySet が確実に得られます。

これは私には少し矛盾しているように思えます。一方では、Django はマネージャ メソッドが任意のオブジェクト タイプを返すようにする自由を提供し、他方ではall()メソッドに QuerySet を必要とします。各マネージャーには、get_querysetによって呼び出されるメソッドがあることを認識していall()ます。all()しかし、カスタム マネージャーでオーバーライドするのを誰が止めますか? 私は同意しますが、そうするのは悪い設計になるでしょう。

  • 私が見る限り、このall()メソッドは QuerySet を返すことを保証していません。正確には何をMyModel.objects返しますか?このステートメントは を呼び出しall()ますか? または `get_queryset()?

  • あなたはどちらを好みますMyModel.objects.filter(...)MyModel.objects.all().filter(...)?もしそうなら、なぜですか?

  • 望ましくない方法でこれらのメソッドを台無しにする不安定なマネージャーに遭遇したことがありますか?

4

3 に答える 3

76

Djangoのソース コードでわかるように、マネージャのメソッドall()は に委譲するだけです。get_queryset()

def all(self):
    return self.get_queryset()

したがって、これは Manager から QuerySet を取得する方法にすぎません。これは、 Manager を返すため、 ManagerではなくQuerySetを扱っていることを確認するのに便利です。MyModel.objects

たとえば、すべてのアイテムを反復処理する場合、次のようにはできません。

for item in MyModel.objects:
    # do something with item

Manager を反復処理できないためです。ただし、all()クエリセットを返します。クエリセットを反復処理できます。

for item in MyModel.objects.all():
    # do something with item

通常、決して上書きしないでくださいall()。上書きできますget_queryset()が、このメソッドはQuerySet を返す必要があります。

filter()またはのようなフィルター メソッドを使用する場合、これらのメソッドは QuerySet にプロキシされるためexclude()、既に QuerySet を持っていることになります。したがって、のようなことをする必要はありません。all().filter()

于 2014-04-02T08:56:47.733 に答える
3
  1. MyModel.objectsマネージャ インスタンスを返します。all()戻りget_query_set()ます。すべてのオブジェクトが必要な場合に備えて、すべてがそこにあると思います。
  2. もうMyModel.objects.filter()1つはメソッド呼び出しが1つ多いため、フィルターを実行する場合、すべてのオブジェクトは必要ありません:)
  3. 目的によります。ただし、マネージャーの基本メソッドをオーバーライドすると、同じ結果形式 (例: QuerySet) が返されます。
于 2014-04-02T07:28:44.427 に答える