Django:从数据库中获取对象,如果没有匹配,则返回“None”

有没有什么Django函数可以让我从数据库中获取对象,或者如果没有匹配的话可以使用None?

现在我正在使用像这样的东西:

foo = Foo.objects.filter(bar=baz) foo = len(foo) > 0 and foo.get() or None 

但是这不是很清楚,到处都是一团糟。

在Django 1.6中,您可以使用第first() Queryset方法。 它返回查询集匹配的第一个对象,如果没有匹配对象则返回None。

用法:

 p = Article.objects.order_by('title', 'pub_date').first() 

有两种方法可以做到这一点;

 try: foo = Foo.objects.get(bar=baz) except model.DoesNotExist: foo = None 

或者你可以使用一个包装器:

 def get_or_none(model, *args, **kwargs): try: return model.objects.get(*args, **kwargs) except model.DoesNotExist: return None 

像这样称呼它

 foo = get_or_none(Foo, baz=bar) 

为了给sorki的答案添加一些示例代码(我将这添加为一个评论,但这是我的第一篇文章,我没有足够的声誉留下评论),我实现了一个get_or_none自定义pipe理器,如下所示:

 from django.db import models class GetOrNoneManager(models.Manager): """Adds get_or_none method to objects """ def get_or_none(self, **kwargs): try: return self.get(**kwargs) except self.model.DoesNotExist: return None class Person(models.Model): name = models.CharField(max_length=255) objects = GetOrNoneManager() 

现在我可以做到这一点:

 bob_or_none = Person.objects.get_or_none(name='Bob') 

你也可以尝试使用django讨厌(它有另一个有用的function!)

安装它:

 pip install django-annoying from annoying.functions import get_object_or_None get_object_or_None(Foo, bar=baz) 

给Foo 定制经理 。 这非常简单 – 只需将自己的代码放入自定义pipe理器中,在您的模型中设置自定义pipe理器,然后使用Foo.objects.your_new_func(...)调用它。

如果你需要generics函数(在任何模型上使用它,而不仅仅是使用自定义pipe理器),编写你自己的代码并把它放在你的pythonpath的某个地方并导入,而不是再乱。

无论是通过pipe理器还是通用函数来完成,你也可能想要在TRY语句中捕获“MultipleObjectsReturned”,因为如果你的kwargs检索多个对象,get()函数会引发这个。

build立在通用function上:

 def get_unique_or_none(model, *args, **kwargs): try: return model.objects.get(*args, **kwargs) except (model.DoesNotExist, model.MultipleObjectsReturned), err: return None 

和经理:

 class GetUniqueOrNoneManager(models.Manager): """Adds get_unique_or_none method to objects """ def get_unique_or_none(self, *args, **kwargs): try: return self.get(*args, **kwargs) except (self.model.DoesNotExist, self.model.MultipleObjectsReturned), err: return None 

以下是助手函数的一个变体,您可以select传入QuerySet实例,以防万一您希望从模型的all对象查询集以外的查询集(例如,从属于子项的子集中获取唯一对象到一个父实例):

 def get_unique_or_none(model, queryset=None, *args, **kwargs): """ Performs the query on the specified `queryset` (defaulting to the `all` queryset of the `model`'s default manager) and returns the unique object matching the given keyword arguments. Returns `None` if no match is found. Throws a `model.MultipleObjectsReturned` exception if more than one match is found. """ if queryset is None: queryset = model.objects.all() try: return queryset.get(*args, **kwargs) except model.DoesNotExist: return None 

这可以以两种方式使用,例如:

  1. obj = get_unique_or_none(Model, *args, **kwargs)
  2. obj = get_unique_or_none(Model, parent.children, *args, **kwargs)

我认为在大多数情况下,你可以使用:

 foo, created = Foo.objects.get_or_create(bar=baz) 

只有在Foo表中添加新条目并不重要时(其他列将具有无/默认值)