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
这可以以两种方式使用,例如:
-
obj = get_unique_or_none(Model, *args, **kwargs)
-
obj = get_unique_or_none(Model, parent.children, *args, **kwargs)
我认为在大多数情况下,你可以使用:
foo, created = Foo.objects.get_or_create(bar=baz)
只有在Foo表中添加新条目并不重要时(其他列将具有无/默认值)