チェーンフィルタリングを行ういくつかのメソッドを持つカスタムQuerySetオブジェクトがあります。まず、コンテキストの設定。
from django.db.models import Manager, Model
from django.db.models.query import QuerySet
class MyQuerySet(QuerySet):
def some_filter(self, foo):
return self.filter(some__chain__of__relationships__foo=foo)
class MyModelManager(Manager):
def get_query_set(self):
return MyQuerySet(self.model, using=self._db)
class MyModel(Model):
objects = MyModelManager()
使用事例:
qs = MyModel.objects.get_query_set()
qs = qs.filter_by_name(name).filter_by_color(color).filter_by_date(date)
私はDjangoのEmptyQuerySetではなく、私のオブジェクトの空のクエリーセットを返す必要がある状況があります。
def filter_by_color(self, color):
if color.is_active:
return self.filter(some__chain__of__relationships__color=color)
return self.empty()
どのように定義するか .empty()
?私は使用することはできません .none()
なぜなら .filter_by_date(date)
EmptyQuerySetにはnoがあるためエラーがスローされます .filter_by_date()
方法。私は現在、ハックを使っています where=["1=0"]
def empty(self):
return self.extra(where=["1=0"])
または...:
def empty(self):
return self.filter(pk=0)
私は非ハックの方法でこれを行うことを好むでしょう。
私のカスタムQuerySetオブジェクトの空のクエリセットを返すPythonの方法は何ですか?
回答:
回答№1は1Django <= 1.5を使用している場合は、 EmptyQuerySet
クラスと独自のカスタムクエリーセットクラスです。ただオーバーライドする none()
あなたのカスタムクラスを返す:
class MyQuerySet(QuerySet):
def none(self):
# prevent circular import
from . import MyEmptyQuerySet
return self._clone(klass=MyEmptyQuerySet)
class MyEmptyQuerySet(EmptyQuerySet, MyQuerySet):
pass
Django 1.6では、あなたが呼んでもquerysetのクラスは同じです none()
しかし、メタクラスの使用とオーバーライド __instancecheck__
、呼び出し isinstance(qs.none(), EmptyQuerySet)
それでも返されます True
。だから、Django 1.6では、カスタムクラスやその他のものは必要ありません。あなたのカスタムクエリーセットクラスの新しいメソッドは、空のクエリーセットでも利用できます。
回答№2の場合は0
qs = qs.filter_by_name(name).filter_by_color(color)
qs = qs.filter_by_date(date) if isinstance(qs, MyQuerySet) else qs
これは私が今すぐ見ることができる最も簡単なことです。あるいは、チェーンの最後に色でフィルターをかけます。