如何使用get_object_or_404排除结果?

问题描述:

在Django中,您可以使用排除来创建类似于not equal的SQL。一个例子可能是。如何使用get_object_or_404排除结果?

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来获得所需的结果?

+0

这不是一个真正的答案,但它似乎不会真的想404软删除对象。软删除的重点是保持对象“以防万一”。 – 2010-06-15 15:07:28

使用django.db.models.Q

from django.db.models import Q 

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

将q对象让你不(与~运营商)和OR(与|运营商)除了和。

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

+0

引起Q对象。不知道它会在那场比赛中奏效。感谢名单。 – googletorp 2010-06-15 23:24:42

+1

除了模型之外,您还可以传递Manager或QuerySet作为第一个参数。请参阅http://*.com/a/26476339/336694 – Heliodor 2015-03-11 17:12:03

还有另一种方式,而不是使用Q对象。相反,模型传递到get_object_or_404的只是通过查询集,而不是功能:这

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

一个副作用,但是,它会提高一个MultipleObjectsReturned异常,如果查询集返回多个结果。

最常见的用例是传递一个模型。但是,你也可以通过一个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

+0

我认为这比接受的答案更容易遵循解决方案。我的意思是,如果我在6个月前查看过我的代码,那么如果我使用Q对象而不是使用排除过滤,我会想让自己在脸上表现出色。 – 2017-03-26 15:28:04

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)