Djangoでは、カスタムマネージャーは再利用可能なクエリロジックを整理する優れた方法です。 Custom managers に関するDjangoのドキュメントは次のように述べています:
Manager
をカスタマイズする理由は2つあります。追加のManager
メソッドを追加すること、および/または最初のQuerySet
を変更すること、Manager
が返すことです。
ただし、 説明を続けます カスタムQuerySet
クラスを作成する方法、およびこれらはQuerySet.as_manager()
を使用して、データモデルからマネージャーとして直接アクセスできるようにすることができます。 :
QuerySet.as_manager()
によって作成されたManager
インスタンスは、前の例のPersonManager
と実質的に同一になります。
カスタムManager
および/またはカスタムQuerySet
クラス間でロジックを整理する方法には、多くの柔軟性があるようです。どちらを使用するかを決定する際の原則は何ですか?
主にクエリを簡単に構成できるようにします。一般に、一連のクエリセット呼び出しの既存のクエリセットに対して何らかの操作を実行したい場合は、QuerySet
を使用できます。
たとえば、Image
、width
フィールドを持つheight
モデルがあるとします。
class Image(models.Model):
width = ... # Width in pixels
height = ... # Height in pixels
いくつかのカスタムQuerySet
メソッドを書くことができます:
class ImageQuerySet(models.QuerySet):
def landscapes(self):
return self.filter(width__gte=models.F('height'))
def portraits(self):
return self.filter(width__lte=models.F('height'))
def small(self):
return self.filter(width__lte=1200)
def large(self):
return self.filter(width__gte=1200)
class ImageManager(models.Manager):
def get_queryset(self):
return ImageQuerySet(self.model, using=self._db)
これで、動的なクエリセットを簡単に作成できます。
Image.objects.all().portraits().small()
Image.objects.all().large().portraits()
論理的には、これらの関数は主に、クエリセットのモデルの既存のクエリセットのパーティション化または再定義に関係する必要があります。既存のクエリセットを操作していない状況では、クエリセットをまったく返さないか、この特定のモデルに関係しないいくつかの関連ロジックを、より適切なモデルマネージャよりも実行する必要がある場合があります。
Manager
とQuerySet
の違いを自分自身で再学習していたので、ここに書いたほうがいいと思ったので、次回は簡単に書けるようにしました。
Manager
は、モデルに接続されているクラスであり、QuerySet
インスタンスを返します。objects
はデフォルトのマネージャーです。ほとんどのマネージャーメソッド、例: all()
、filter()
はクエリセットインスタンスを返します。
より詳細には、YourModel.objects.filter(..)
を実行すると、クエリセットインスタンスが取得されます。再度フィルタリングする場合は、QuerySet
クラスでも使用できるため、別の.filter(..)
メソッドをチェーンできます。それはあなたが望むことです..マネージャーとそれが返すクエリセットの両方にあなたのメソッドを持っています。
filter
もマネージャーメソッドではなかった場合は、YourModel.objects.all()
を実行してクエリセットを取得し、その後そこからfilter
メソッドを追加します。
物事を簡単にするために、DjangoはQuerySetクラスのas_manager()
メソッドを定義し、それをマネージャーに変換します [docs] =。したがって、クエリセットですべてのカスタムメソッドを定義し、それをマネージャーに変換してモデルにアタッチすることで、最初に(マネージャーメソッドとして)呼び出して、必要なだけチェーンすることができます。 (querysetメソッドとして)。
この回答を書いて、クエリセットメソッドではないDjangoに同梱されているマネージャーメソッドがあるかどうか疑問に思いました。最初に頭に浮かんだのは_get_or_create
_メソッドでした。クエリセットは必要ないようですが、何だと思いますか?これもQuerySet
クラスで定義されていることがわかりました。
簡単に言えば、ほとんどの場合、QuerySetメソッドを記述し、as_manager()
を介してそれらもマネージャーに配置する必要があります。