Django QuerySet - 如何“禁用”以前的过滤值

Posted

技术标签:

【中文标题】Django QuerySet - 如何“禁用”以前的过滤值【英文标题】:Django QuerySet - How to "disable" previous filtered value 【发布时间】:2013-09-29 15:08:49 【问题描述】:

我有一个基础模型类,它会在每次更改对象时创建对象的历史记录。该模型具有名为“is_history”的字段。这个想法是,每次有人更改模型时,都会使用旧数据创建模型的新实例。具有旧数据的新模型具有“is_history=True”,因为它成为历史对象。 在默认的管理员更改列表中,我不想看到历史对象。默认情况下,我不想在任何地方看到它们。这就是为什么我创建了覆盖默认 get_query_set() 并添加“is_history=False”的新管理器。

def get_query_set(self):
    qs = super(ModelHistoryManager, self).get_query_set()
    return qs.filter(is_history=False)

但我也应该能够很少在更改列表视图中显示历史对象,例如使用管理过滤器。

我的问题是:我有一个已经过滤了这个值的查询集。但是在管理员的过滤器中,我从基本管理器获取过滤后的查询集,我想将此过滤器从 is_history=False 更改为 is_history=True,或者如果用户想要显示所有记录,则删除“is_history”的过滤器 - 两个历史记录和原始记录。

有什么想法吗?

【问题讨论】:

为什么不创建两个经理?对于管理员和非管理员? 如何过滤admin中的值呢?管理员使用标准对象管理器。所有这些事情都发生在管理员的上下文中,而不是在自定义视图中。 是的,我明白了。为什么不在自定义视图中使用自定义管理器?或者,您可以创建一个抽象模型并在管理员中使用它。从原来的扩展它并覆盖其中的默认管理器。 带有自定义管理员的自定义管理器不能解决问题。管理员将应用经理的“is_history=False”过滤器,但稍后在管理员的过滤器中我必须更改此值..sooo 我必须再次更改查询集..自定义管理员不是我认为的解决方案:/ 对不起,我有点困惑。您可以在 ModelAdmin 中覆盖 queryset 方法并返回“纯”查询集用于管理事务。 【参考方案1】:

让我引用关于Custom Managers 的django 文档:

如果您使用自定义 Manager 对象,请注意第一个 Manager Django 遇到(按照它们在模型中定义的顺序) 有着特殊的地位。 Django 解释第一个 Manager 中定义的 作为“默认”管理器的类,以及 Django 的几个部分(包括 dumpdata) 将为该模型专门使用该 Manager。作为一个 因此,谨慎选择默认值是个好主意 经理以避免覆盖 get_query_set() 的情况 导致无法检索您想要使用的对象。

所以,你应该这样做:

class MyModel(Model):
    objects = models.Manager() # The default manager.
    custom_manager = MyCustomManager() # This has overrided the get_query_set method

当然,如果你想要过滤模型实例,你应该使用custom_manager 而不是objects

【讨论】:

我知道这件事。但我必须根据过滤值更改结果。如果用户已按此字段应用过滤器,我必须从第二个经理创建一个新的查询集,以应用管理员的所有过滤器并返回查询集。如果用户没有应用任何过滤器,则必须返回默认查询集。这些过滤器选项在管理员的过滤器中管理,在 get_query_set() 中没有。【参考方案2】:

您可以破解它,但让我警告您,这是一个非常糟糕的主意,并且会触及用户不应触及的内部结构。但如果你坚持,这会成功:

from django.db.models.sql.where import WhereNode
qs.query.where = WhereNode()

【讨论】:

以上是关于Django QuerySet - 如何“禁用”以前的过滤值的主要内容,如果未能解决你的问题,请参考以下文章

django-select2:如果没有选择国家,如何禁用城市选择? (django 2.2)

修改django管理字段以使用特定的queryset和表单小部件

Django - 如何将 QuerySet 转换为 Q 对象?

如何在 Django 中覆盖“get_queryset()”

DJango filter_queryset

禁用多选 Django 小部件中的选择