我有一个第三方函数,它给了我一个过滤的查询集(例如'valid'= True的记录),但我想删除一个特定条件(例如,要有所有记录,有效和无效)。
有没有办法将筛选条件移除到已经过滤的查询集?
E.g。
only_valid = MyModel.objects.filter(valid=True)
all_records = only_valid.**remove_filter**('valid')
(我知道在'only_valid'之前定义'all_records'会更好,但这只是一个例子......)
答案 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。