在 Django 中,如何优雅地将查询集过滤器添加到大型组或对象的所有成员?

Posted

技术标签:

【中文标题】在 Django 中,如何优雅地将查询集过滤器添加到大型组或对象的所有成员?【英文标题】:In Django, how do I gracefully add a queryset filter to a large group or all members of an object? 【发布时间】:2015-02-07 09:49:51 【问题描述】:

我们目前有一个媒体项目模型,其发布日期决定了项目何时显示在我们的网站上。我们被要求添加指定打开项目的日期范围的功能。如果项目没有关联的日期范围,则其发布日期将决定它是否显示。如果它有日期范围,那么它必须同时发布并且必须在指定的日期范围之一内才能显示在网站上。

现在最明显的方法是检查并修改我们代码中的每个查询集,添加一个过滤器以排除具有日期范围但不属于其中任何一个的项目。但是我们有很多这样的查询集,几乎所有这些查询集都需要更改。所以我想知道是否有一些中心位置可以添加此过滤器,以便它影响所有查询集。

当然,这需要以某些查询(即管理中的媒体项目列表)仍会显示所有项目的方式完成。因此,我所追求的更多是一种优雅的方式来影响具有特定过滤器的一大组查询集,而无需在代码中找到每个实例。有什么想法吗?

【问题讨论】:

【参考方案1】:

这正是custom model managers 的用途。定义一个经理子类并用您的查询覆盖get_query_set。然后,您需要首先明确定义一个默认管理器,然后调用您的自定义管理器objects,它应该就可以工作了。

请注意,即使您可以这样做,我也建议您不要这样做。至少,将您的自定义管理器称为其他名称 - 例如restricted - 并在您的代码中进行搜索和替换,以替换对自定义版本的对象的引用。这样一来,阅读您的代码的人就会意识到该查询不是标准查询。

【讨论】:

【参考方案2】:

您正在寻找model managers。

类似:

class MediaItemManager(models.Manager):
    def get_queryset(self):
        return super(MediaItemManager, self).get_queryset().filter(...)

您可以将其设置为模型上的默认管理器,如下所示:

class MediaItem(models.Model):
    objects = MediaItemManager()
    all_objects = models.Manager()

您可以通过在 ModelAdmin 子类上指定 get_queryset 来确保这不会影响管理员:

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = self.model.all_objects.get_queryset()
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

这是对基本@9​​87654322@ 的相当不幸的重复,因为没有办法明确地覆盖管理员的经理。更好的选择可能是将您的自定义管理器命名为filtered_objects,并将默认管理器命名为objects

【讨论】:

感谢大家的帮助。到目前为止,真的没有过多地研究经理,所以这对我来说将是一次新的冒险。不过隧道尽头有光!

以上是关于在 Django 中,如何优雅地将查询集过滤器添加到大型组或对象的所有成员?的主要内容,如果未能解决你的问题,请参考以下文章

我想在 Django 中进行两个查询集搜索

如何在 Django 查询集过滤中执行不等于?

Django模型查询集过滤器作为一个函数

如何在 django 中过滤查询集的多对多

如何使用动态过滤器制作 django 查询集?

有没有办法检查字符串是不是是 django 查询集的有效过滤器?