【问题标题】:How to empty a Django Queryset如何清空 Django 查询集
【发布时间】:2014-08-28 07:35:58
【问题描述】:

我有一个自定义的 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 对象的空查询集?

【问题讨论】:

    标签: django django-queryset


    【解决方案1】:

    如果您使用的是 Django 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) 仍将返回 True。所以在 Django 1.6 中,不需要自定义类或任何东西,自定义查询集类上的新方法仍然可以在空查询集上使用。

    【讨论】:

    • 我担心可能是这种情况。我真的,真的不想创建自己的EmptyQuerySet,但这就是生活。谢谢。
    【解决方案2】:
    qs = qs.filter_by_name(name).filter_by_color(color)
    qs = qs.filter_by_date(date) if isinstance(qs, MyQuerySet) else qs
    

    这是我现在能看到的最简单的东西。或者在链的末尾按颜色过滤。

    【讨论】:

    • 这对用例来说太具体了,需要我知道过滤器的链接顺序。如果任何/所有过滤器都可以返回 EmptyQuerySet 对象怎么办?这种实现不够通用。
    猜你喜欢
    • 2012-03-29
    • 2013-04-22
    • 1970-01-01
    • 2018-12-01
    • 2013-06-30
    • 2012-04-14
    • 2010-11-26
    • 2020-10-08
    • 2021-11-30
    相关资源
    最近更新 更多