如何使用get_object_or_404排除结果?

时间:2010-06-15 15:03:59

标签: python django orm

在Django中,您可以使用exclude来创建类似于not equal的SQL。一个例子可能是。

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

现在这很好用,排除非常灵活。由于我有点懒,我想在使用get_object_or_404时获得该功能,但我还没有找到一种方法来执行此操作,因为您无法在get_object_or_404上使用排除。

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

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

但不幸的是,这不起作用,因为没有排除查询过滤器或类似的。到目前为止,我提出的最好的做法是做这样的事情:

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 个答案:

答案 0 :(得分:16)

使用django.db.models.Q

from django.db.models import Q

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

除了AND之外,Q对象不允许(使用~运算符)和OR(使用|运算符)。

请注意,Q对象必须在pk=id之前,因为关键字参数必须在Python中排在最后。

答案 1 :(得分:6)

最常见的用例是传递模型。但是,您也可以传递QuerySet实例:

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

Django docs示例: https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#id2

答案 2 :(得分:1)

还有另一种方法,而不是使用Q对象。而不是将模型传递给get_object_or_404而只是将QuerySet传递给函数:

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

然而,这样做的一个副作用是,如果QuerySet返回多个结果,它将引发MultipleObjectsReturned异常。

答案 3 :(得分:0)

get_object_or_404使用对象管理器的get_queryset方法。如果您覆盖get_queryset方法,则仅返回未被删除且"然后get_object_or_404会自动按您的意愿行事。但是,像这样覆盖get_queryset可能会在其他地方(可能在管理页面中)出现问题,但您可以在需要访问软删除项目时添加备用管理器。

from django.db import models

class ModelManger(models.Manger):
    def get_queryset(self):
        return super(ModelManger, self).get_queryset().exclude(status='deleted')

class Model(models.Model):
    # ... model properties here ...

    objects = ModelManager()
    all_objects = models.Manager()

因此,如果您只需要未删除的项目,则可以执行get_object_or_404(Models, id=id)但如果您需要所有项目,则可以执行get_object_or_404(Models.all_objects, id=id)