如果存在该对象,该如何获取;如果该对象不存在,该如何获取?
当我让模型pipe理器获得一个对象时,当没有匹配的对象时,它会引发DoesNotExist
。
go = Content.objects.get(name="baby")
而不是DoesNotExist
,我怎么能成为None
而不是?
没有“内置”的方式来做到这一点。 Django每次都会引发DoesNotExistexception。 在Python中处理这个问题的惯用方法是将其封装在try catch中:
try: go = SomeModel.objects.get(foo='bar') except SomeModel.DoesNotExist: go = None
我所做的就是将models.Manager创build子类,像上面的代码一样创build一个safe_get
,并将该pipe理器用于我的模型。 这样你可以写: SomeModel.objects.safe_get(foo='bar')
。
因为django 1.6你可以使用first()方法:
Content.objects.filter(name="baby").first()
从Django的文档
如果找不到给定参数的对象,则
get()
会引发一个DoesNotExist
exception。 这个exception也是模型类的一个属性。DoesNotExist
exceptioninheritance自django.core.exceptions.ObjectDoesNotExist
你可以捕捉到exception,并指定None
去。
from django.core.exceptions import ObjectDoesNotExist try: go = Content.objects.get(name="baby") except ObjectDoesNotExist: go = None
你可以为此创build一个通用函数。
def get_or_none(classmodel, **kwargs): try: return classmodel.objects.get(**kwargs) except classmodel.DoesNotExist: return None
使用如下所示:
go = get_or_none(Content,name="baby")
如果没有条目匹配,则go将是None,否则将返回Content条目。
注意:如果多于一个入口返回name =“baby”,将引发exceptionMultipleObjectsReturned
为了使事情更容易,下面是我写的代码的一小部分,根据这里精彩的答复的input:
class MyManager(models.Manager): def get_or_none(self, **kwargs): try: return self.get(**kwargs) except ObjectDoesNotExist: return None
然后在你的模型中:
class MyModel(models.Model): objects = MyManager()
而已。 现在你有MyModel.objects.get()以及MyModel.objetcs.get_or_none()
你可以使用exists
与filter:
Content.objects.filter(name="baby").exists() #returns False or True depending on if there is anything in the QS
只是一个select,如果你只想知道它是否存在
这是您可能不希望重新实现的令人讨厌的function之一:
from annoying.functions import get_object_or_None #... user = get_object_or_None(Content, name="baby")
你可以这样做:
go = Content.objects.filter(name="baby").first()
现在variables可以是你想要的对象或None
参考: https : //docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
处理视图中不同点的exception真的很麻烦。关于如何在models.py文件中定义一个自定义模型pipe理器
class ContentManager(model.Manager): def get_nicely(self, **kwargs): try: return self.get(kwargs) except(KeyError, Content.DoesNotExist): return None
然后将其包含在内容Model类中
class Content(model.Model): ... objects = ContentManager()
通过这种方式,可以很容易地处理的意见,即
post = Content.objects.get_nicely(pk = 1) if post: # Do something else: # This post doesn't exist
如果你想要一个简单的单行解决scheme,不涉及exception处理,条件语句或者Django 1.6+的需求,那就这样做:
x = next(iter(SomeModel.objects.filter(foo='bar')), None)
以下是助手函数的一个变体,您可以select传入QuerySet
实例,以防万一您希望从模型的all
对象查询集以外的查询集(例如,从属于子项的子集中获取唯一对象到一个父实例):
def get_unique_or_none(model, queryset=None, **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(**kwargs) except model.DoesNotExist: return None
这可以以两种方式使用,例如:
-
obj = get_unique_or_none(Model, **kwargs)
-
obj = get_unique_or_none(Model, parent.children, **kwargs)
毫无例外:
if SomeModel.objects.filter(foo='bar').exists(): x = SomeModel.objects.get(foo='bar') else: x = None
使用exception:
try: x = SomeModel.objects.get(foo='bar') except SomeModel.DoesNotExist: x = None
关于何时应该在python中使用exception有一些争论。 一方面,“请求宽恕比允许要容易”。 虽然我同意这一点,但我认为应该保留一个例外,那就是例外,“理想的情况”应该不会碰到一个例外。
从Django 1.7开始,你可以这样做:
class MyQuerySet(models.QuerySet): def get_or_none(self, **kwargs): try: return self.get(**kwargs) except self.model.DoesNotExist: return None class MyBaseModel(models.Model): objects = MyQuerySet.as_manager() class MyModel(MyBaseModel): ... class AnotherMyModel(MyBaseModel): ...
“MyQuerySet.as_manager()”的优点是以下两个方法都可以工作:
MyModel.objects.filter(...).get_or_none() MyModel.objects.get_or_none()
我们可以使用Django内置的exception附加到名为.DoesNotExist
的模型。 所以,我们不必导入ObjectDoesNotExist
exception。
而是做:
from django.core.exceptions import ObjectDoesNotExist try: content = Content.objects.get(name="baby") except ObjectDoesNotExist: content = None
我们做得到:
try: content = Content.objects.get(name="baby") except Content.DoesNotExist: content = None
我认为使用get_object_or_404()
是不错的主意
from django.shortcuts import get_object_or_404 def my_view(request): my_object = get_object_or_404(MyModel, pk=1)
这个例子相当于:
from django.http import Http404 def my_view(request): try: my_object = MyModel.objects.get(pk=1) except MyModel.DoesNotExist: raise Http404("No MyModel matches the given query.")
您可以在django在线文档中阅读关于get_object_or_404()的更多信息。