为什么Django MultipleObjectsReturned错误占用内存?

时间:2017-03-07 09:44:28

标签: django django-queryset

我正在使用Django 1.9.10:

我有一个名为Details的模型,其unique_id列已被编入索引:

 try:
     detail = Detail.objects.get(unique_id=UUID)
 except MultipleObjectsReturned as m:
     logger.error("uuid {} returned multiple objects - {}".format(UUID, str(m)))

由于代码UUID=None出现了一些错误,导致MultipleObjectsReturned出现错误。但是我们注意到几乎2 GB的内存正在耗尽,而且它正在大大减慢系统速度。

在错误日志中打印str(m)时,我们发现以下错误

  

MultipleObjectsReturned:get()返回多个详细信息 - 它返回451424!

我的问题是为什么Django只是为了引发错误而在内存中获取如此多的数据? Django可以获取计数吗?

我知道我可以使用filter()来解决这个问题,但我对此感到惊讶,并想了解为什么django会这样做?

3 个答案:

答案 0 :(得分:3)

因为这是在内部完成的:

def get(self, *args, **kwargs):
    """
    Perform the query and return a single object matching the given
    keyword arguments.
    """
    clone = self.filter(*args, **kwargs) # calling `filter()` inside
    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)
    )

查看完整的来源here

我想你想知道为什么它不能只取这个数字?因为它会向数据库发出两个请求,而不是一个。一个获取计数的请求和一个获取数据的请求。

你怎么解决?您可以更改应用程序逻辑以避免这种情况。断言UUID不是None。或者在进行实际查询之前获取count

关于get的文档:https://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-a-single-object-with-get

答案 1 :(得分:1)

因为你知道你不应该得到多个对象时使用.get。

如果在返回451424项目的情况下选择使用它而不是它的设计目的。

答案 2 :(得分:0)

因为您在数据库中有多个具有相同ID的人。 将您的查询重写为:Detail.objects.filter(unique_id=UUID)