我有一个自定义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没有.filter_by_date()
方法。我目前正在使用黑客where=['1=0']
def empty(self):
return self.extra(where=['1=0'])
或者...
def empty(self):
return self.filter(pk=0)
我更愿意以非黑客的方式做到这一点。
什么是Pythonic方式返回自定义QuerySet对象的空查询集?
答案 0 :(得分:1)
如果你正在使用Django< = 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中,如果您调用none()
,则查询集的类仍然相同,但通过使用元类并覆盖__instancecheck__
,调用isinstance(qs.none(), EmptyQuerySet)
仍会返回{{1} }}。因此,在Django 1.6中,不需要自定义类或任何东西,您的自定义查询集类上的新方法仍然可用于空的查询集。
答案 1 :(得分:0)
qs = qs.filter_by_name(name).filter_by_color(color)
qs = qs.filter_by_date(date) if isinstance(qs, MyQuerySet) else qs
这是我现在能看到的最简单的事情。或者在链的末尾按颜色过滤。