在Get / Filter中检查Django ORM中是否存在对象的更好方法是什么?

时间:2017-07-18 05:17:14

标签: python mysql django django-models django-views

让我们考虑一下我是否想找到主键20的用户是否存在?我可以用两种方式做到这一点。

第一个:

try:
   user = User.objects.get(pk=20)
except User.DoesNotExist:
   handle_non_existent_user()

另一种方式可能是:

users = User.objects.filter(pk=20)
if not users.exists():
   handle_non_existent_user()

哪种方法可以检查存在?

这可能与此有关:What is the best way to check if data is present in django? 但是,由于指定的示例没有模型查询集的引用,人们更喜欢第一种方法。

同样在以下问题的答案中:what is the right way to validate if an object exists in a django view without returning 404? 它主要是因为我们没有得到有问题的对象的参考。

2 个答案:

答案 0 :(得分:1)

TLDR:对于几乎总是确定对象是db的情况,最好使用try:get来处理当对象不存在的可能性为50%的情况时最好使用if:filter.exists

这实际上取决于代码上下文。例如,有些情况if语句优于try/except Using try vs if in python

所以对于你的问题,它是相同的Difference between Django's filter() and get() methods。调用get

下面的filter方法

https://github.com/django/django/blob/stable/1.11.x/django/db/models/query.py#L366

def get(self, *args, **kwargs):
    """
    Performs the query and returns a single object matching the given
    keyword arguments.
    """
    clone = self.filter(*args, **kwargs)
    if self.query.can_filter() and not self.query.distinct_fields:
        clone = clone.order_by()
    num = len(clone)
    if num == 1:
        return clone._result_cache[0]
    if not num:
        raise self.model.DoesNotExist(
            "%s matching query does not exist." %
            self.model._meta.object_name
        )
    raise self.model.MultipleObjectsReturned(
        "get() returned more than one %s -- it returned %s!" %
        (self.model._meta.object_name, num)
    )

因此,如果您将filterexists一起使用。它会执行几乎相同的代码,因为下面的exists会执行此操作

def exists(self):
    if self._result_cache is None:
        return self.query.has_results(using=self.db)
    return bool(self._result_cache)

正如您所看到的,filter.exists将执行更少的代码并且应该更快地工作,但它不会返回给您一个对象。

答案 1 :(得分:0)

在我看来,第一个是最好的方法,因为如果我忘记检查用户是否存在,即使我不使用try / except子句,它也会给我一个错误。

此外,get专门用于获得一件商品。