如何在get_object_or_404中排除结果?

23 投票
4 回答
13860 浏览
提问于 2025-04-16 00:00

在Django中,你可以使用exclude来创建类似于不等于的SQL查询。比如说,下面这个例子:

Model.objects.exclude(status='deleted')

这个方法效果很好,而且exclude非常灵活。不过因为我有点懒,我希望在使用get_object_or_404的时候也能有这样的功能,但我找不到办法,因为在get_object_or_404上不能使用exclude。

我想做的事情大概是这样的:

model = get_object_or_404(pk=id, status__exclude='deleted')

但不幸的是,这样做不行,因为没有exclude查询过滤器或者类似的东西。我目前想到的最好办法是这样:

object = get_object_or_404(pk=id)
if object.status == 'deleted':
    return HttpResponseNotfound('text')

这样做的话,实际上就失去了使用get_object_or_404的意义,因为它不再是一个方便的一行代码了。

另外,我可以这样做:

object = get_object_or_404(pk=id, status__in=['list', 'of', 'items'])

但这样就不太好维护,因为我需要不断更新这个列表。

我在想,是不是我在Django中漏掉了什么技巧或者功能,能让我用get_object_or_404得到想要的结果呢?

4 个回答

1

还有一种方法可以替代使用 Q 对象。你可以不把模型传给 get_object_or_404,而是直接把查询集(QuerySet)传给这个函数:

model = get_object_or_404(MyModel.objects.filter(pk=id).exclude(status='deleted'))

不过这样做有一个副作用,就是如果查询集返回了多个结果,它会抛出一个 MultipleObjectsReturned 的异常。

15

最常见的用法是传递一个模型(Model)。不过,你也可以传递一个查询集(QuerySet)实例:

queryset = Model.objects.exclude(status='deleted')
get_object_or_404(queryset, pk=1)

这是Django文档中的一个例子: https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#id2

23

使用 django.db.models.Q

from django.db.models import Q

model = get_object_or_404(MyModel, ~Q(status='deleted'), pk=id)

Q对象让你可以使用 NOT(用 ~ 操作符)和 OR(用 | 操作符),除了 AND 之外。

需要注意的是,Q对象必须放在 pk=id 之前,因为在Python中,关键字参数必须放在最后。

撰写回答