获取结果列表,每个外键1个

时间:2014-04-29 18:58:50

标签: python mysql django

我有一个模型Reading,它有一个外键Type。我正在尝试使用以下代码获取每种类型的读数:

    for type in Type.objects.all():
        readings = Reading.objects.filter(
                type=type.pk)
        if readings.exists():
            reading_list.append(readings[0])

当然,问题在于它会在每次传感器读数时触及数据库。我已经玩了一些查询,试图将其优化为单个数据库调用,但它们似乎都没有效率。例如,.values将为我提供按类型分组的读数列表,但它会给我每种类型的每个读数,我必须在内存中使用Python过滤它们。这是不可能的,因为我们正在处理数百万的读数。

1 个答案:

答案 0 :(得分:0)

如果您使用PostgreSQL作为您的数据库后端,您可以通过以下方式在一行中执行此操作:

Reading.objects.order_by('type__pk', 'any_other_order_field').distinct('type__pk')

请注意,发生异常的字段必须始终是order_by方法中的第一个参数。您可以使用要在其上订购类型的确认字段更改type__pk(例如,如果type__name模型具有Type属性,则为name)。您可以在此处详细了解不同的https://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct

如果您不使用PostgreSQL,可以使用prefetch_related方法实现此目的:

#reading_set could be replaced with whatever your reverse relation name actually is
for type in Type.objects.prefetch_related('reading_set').all():
        readings = type.reading_set.all()
        if len(readings):
            reading_list.append(readings[0])

以上只会执行2个查询。注意我使用len(),这样在计算对象时不会执行额外的查询。您可以在此处详细了解prefetch_related https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related

这种方法的缺点是你首先从数据库中检索所有相关对象然后得到第一个。

以上代码未经过测试,但我希望它至少能指向正确的方向。