Django:从查询集中删除过滤条件

时间:2011-01-14 09:20:31

标签: django django-models filtering django-queryset

我有一个第三方函数,它给了我一个过滤的查询集(例如'valid'= True的记录),但我想删除一个特定条件(例如,要有所有记录,有效和无效)。

有没有办法将筛选条件移除到已经过滤的查询集?

E.g。

only_valid = MyModel.objects.filter(valid=True)
all_records = only_valid.**remove_filter**('valid')

(我知道在'only_valid'之前定义'all_records'会更好,但这只是一个例子......)

6 个答案:

答案 0 :(得分:11)

虽然使用过滤器表示法没有正式的方法来执行此操作,但您可以使用Q - 表示法轻松完成此操作。 例如,如果确保第三方函数返回Q对象而不是已过滤的QuerySet,则可以执行以下操作:

q = ThirdParty()
q = q | Q(valid=False)

生成的SQL条件将使用OR运算符连接。

答案 1 :(得分:4)

来自the docs

  

每次优化QuerySet时,都会得到一个全新的QuerySet,它不会绑定到之前的QuerySet。每个细化都会创建一个独立且独特的QuerySet,可以存储,使用和重用。

我怀疑,有一种标准的方法可以做到这一点。你可以dig into the code看看filter()做了什么,然后尝试一下。如果这没有帮助,我的假设是,你运气不好,需要自己重新构建查询。

答案 2 :(得分:1)

这是我在类似案例中所做的。

all_records = MyModel.objects.all()
only_valid = MyModel.objects.filter(valid=True)
only_valid.original = all_records

...

all_records = only_valid.original

显然,这也会清除任何其他过滤器,因此不适合所有情况。

答案 3 :(得分:0)

感谢您让我查看源代码Boldewyn。所以,似乎在filter()下面有一个新方法,它具有相同的参数......名为exclude()(从提交迷你哈希ef6c680开始,当它丢失其行号时)

  

返回一个新的QuerySet实例,其中NOT(args)ANDed到现有集合。

所以,回答原来的问题:

only_valid = MyModel.objects.filter(valid=True)
filtered_results = only_valid.exclude(the_condition_to_remove=True)

答案 4 :(得分:0)

使用此功能

from django.db.models import Q

def remove_filter(lookup, queryset):
    """
    Remove filter lookup in queryset
    ```
    >>> queryset = User.objects.filter(email='user@gmail.com')
    >>> queryset.count()
    1
    >>> remove_filter('email', queryset)
    >>> queryset.count()
    1000
    ```
    """
    query = queryset.query
    q = Q(**{lookup: None})
    clause, _ = self._add_q(q, self.used_aliases)

    def filter_lookups(child):
        return child.lhs.target != clause.children[0].lhs.target

    query.where.children = list(filter(filter_lookups, query.where.children))

答案 5 :(得分:0)

original_query_set = MyModel.objects.filter(**conditions)
model_class = orginal_query_set.model
new_query_set = model_class.objects.filter(**new_conditions)

您可以在QuerySet上使用.model属性来获取模型类,然后使用模型类来创建全新的QuerySet。