【问题标题】:Modify default queryset in django修改 django 中的默认查询集
【发布时间】:2011-01-30 11:19:23
【问题描述】:

我在我的模型中添加了一个“取消”字段,有没有办法将模型默认查询修改为 cancelled=False 之类的东西?无需修改我的所有过滤/排除查询?

【问题讨论】:

    标签: python django django-models metaprogramming


    【解决方案1】:

    您可以使用自定义模型管理器执行此操作,并覆盖 get_queryset 函数以始终过滤 cancelled=False。

    class CustomManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filter(canceled=False)
    
    class MyModel(models.Model):
        # Blah blah
        objects = CustomManager()
    

    然后在调用MyModel.objects.all() 时,它总是会排除已取消的对象。这是一篇我发现对这个主题很有帮助的博客文章。 http://www.b-list.org/weblog/2006/aug/18/django-tips-using-properties-models-and-managers/

    编辑: 也许使用自定义管理器的更好方法是将其附加到另一个属性,而不是对象,例如:

    class MyModel(models.Model):
        # Blah blah
        active = CustomManager()
    

    在您看来,您的查询类似于MyModel.active.all()

    编辑2: 将现代版 django 的方法拼写从 get_query_set 更新为 get_queryset

    【讨论】:

    • 你必须非常非常小心地像这样覆盖默认管理器。在这种特殊情况下,一旦项目被取消,您将永远无法使用 filter()/get() 找到它。
    • 同意。如果给出了 pk,我通常会通过覆盖 get() 来补充这种方法以不使用此过滤器。您可能还希望更改管理查询集以返回所有内容,包括取消。但是,如果您很少希望在查询中取消项目,这可能是一种合理的方法。
    • 嗨,有没有办法修改 get_query_set 的行为以使用附加参数,即从某处传递,或使用全局变量,如当前登录用户信息?谢谢!
    • 想知道get_query_set 的拼写是从哪里来的。我相信正确的方法名称是get_queryset
    • 是的,旧名称 get_query_set 在 1.6 中已弃用并在 1.8 中删除:docs.djangoproject.com/en/1.10/internals/deprecation/…
    【解决方案2】:

    您可以编写自定义query manager,但我认为这不是正确的方法。这将为过滤器创建一个隐含的隐藏条件,从而使代码不可读。记住 Python 之禅:Explicit is better than implicit。检测需要添加 cancelled=False 的地方,然后添加这个,这就是你应该这样做的方式。

    【讨论】:

    • 我强烈反对。那么,拥有自定义管理器的意义何在? not_cancelled = CustomManager() 然后使用 MyModel.not_cancelled.all() 有什么隐含意义?
    猜你喜欢
    • 2012-09-03
    • 2017-05-09
    • 2019-12-08
    • 2013-04-03
    • 2018-09-09
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 2021-11-23
    相关资源
    最近更新 更多