.filter() 和 .get() 处理单个对象的区别?(Django)
我和一些同事在讨论这个问题。想知道在Django中,当你只期望得到一个对象时,有没有更好的获取方式。
有两种明显的方法:
try:
obj = MyModel.objects.get(id=1)
except MyModel.DoesNotExist:
# We have no object! Do something...
pass
还有:
objs = MyModel.objects.filter(id=1)
if len(objs) == 1:
obj = objs[0]
else:
# We have no object! Do something...
pass
第一种方法看起来在行为上更正确,但它在控制流程中使用了异常,这可能会带来一些额外的开销。第二种方法比较绕,但不会引发异常。
大家觉得这两种方法中哪种更好呢?哪种更高效呢?
14 个回答
20
1 是对的。在 Python 中,抛出一个异常和返回一个值所花费的资源是差不多的。你可以看看 这个链接
,里面有个简单的证明。2 这就是 Django 在后台所做的事情。get
方法会调用 filter
,如果没有找到任何项目,或者找到多个对象,就会抛出一个异常。
31
你可以安装一个叫做 django-annoying 的模块,然后这样做:
from annoying.functions import get_object_or_None
obj = get_object_or_None(MyModel, id=1)
if not obj:
#omg the object was not found do some error stuff
212
get()
这个方法是专门为这种情况提供的,建议你使用它。
选项2几乎就是Django中get()
方法的实际实现方式,所以在性能上应该没有什么区别。而且,如果你在考虑这个问题,说明你可能违反了编程的一条重要原则,那就是在代码还没写出来、也没测试之前就想着优化代码——在你有了代码并能运行它之前,你根本不知道它的性能如何,提前优化只会让你走上痛苦的道路。