如何编辑查询集的筛选器列表

时间:2011-03-07 13:46:19

标签: python django

此功能用于我列出搜索结果的视图中。在我的搜索表单中,我有一些ModelChoiceFields可以通过外键进行搜索。通常的工作流程意味着我们当前的搜索越来越精确,所以要禁用许多不相关的结果,我正在尝试删除如果没有其他搜索参数发生变化就不会返回结果的条目。

我正在使用对象查询集来限制某些下拉列表中的命题。 我使用这些下拉列表来过滤外键我的对象列表。

我的filter函数参数现在是一个Objects查询集:

class MySearchForm(Form):
    things = ModelChoiceField(queryset=models.Thing.objects.none())
    def __init__(self, *args, **kwargs):
        my_objects_queryset = kwargs.pop('my_objects_queryset',models.Thing.objects.all())
        super(MySearchForm, self).__init__(*args, **kwargs)
        self.fields['things'].queryset = \
            models.Thing.objects.filter(object__in=my_objects_queryset).distinct()

我的问题是如何从现有的query_set中删除'where close'。 在这里,我想从my_objects_queryset中删除哪个过滤了thing = ForeignKey(models.Thing)

的过滤器

有可能吗?

类似于列出查询集的所有过滤器并动态编辑/删除它们的方法。

2 个答案:

答案 0 :(得分:6)

简答:

不,你不能那样做。

答案很长:

理论上,它可能(在某种程度上),但当然不可取

(我还没有完全研究过django源代码,所以接下来是简单地爬上调用树的结果。)

查看source for QuerySetfilter()exclude()会返回查询集本身的克隆,并添加新规则(使用clone.query.add_q())。

clone.queryobject representing an SQL Query,而add_q()方法将新规则添加到clone.query.wheretree本质上是generated的根节点。

如何将新节点添加到树中取决于规则是与AND还是OR子句连接。这很重要,因为它会影响最终SQL查询的正确性django.utils.tree

因此,要列出分配给查询集的过滤器,一个“简单”需要了解queryset.query.where树的表示方式(请参阅{{3}})。

困难的一点当然是删除过滤器,这样它不会影响剩余的规则。我将不提供解决方案,因为无法保证实施不会因此而使解决方案无效。我怀疑这是可能的,但它的气味应该只是出于学术兴趣,或者根本没有。

答案 1 :(得分:6)

有些黑客入侵。

您可以通过“重置”当前过滤器来绕过它,如下所示:

from django.db.models.sql.where import WhereNode

qs = YourModel.objects.filter(column=1).all()
qs.query.where = WhereNode() # resets current filters
qs.all() # now you can apply new filters