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



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

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

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

您正在寻找模型管理器。

像这样:

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

这是基本get_queryset方法的相当不幸的重复,因为无法显式覆盖管理员的经理。更好的选择可能是将自定义管理器命名为 filtered_objects ,并使用默认管理器作为 objects

这正是自定义模型管理器的用途。定义管理器子类并使用查询覆盖get_query_set。然后,您需要显式定义默认管理器,然后调用自定义管理器objects,它应该可以正常工作。

请注意,即使您可以这样做,我也建议您不要这样做。至少,调用自定义管理器的其他内容(例如restricted(,并在代码中搜索和替换,以将对对象的引用替换为自定义版本。这允许阅读您的代码的人意识到查询不是标准的查询。

最新更新