从 Django Queryset 获取值列表的最有效方法

Posted

技术标签:

【中文标题】从 Django Queryset 获取值列表的最有效方法【英文标题】:Most Efficient Way to get list of values from Django Queryset 【发布时间】:2013-06-04 05:38:11 【问题描述】:

我可以看到很多不同的选项来执行此操作,并希望获得有关最有效或“最佳实践”方法的一些反馈。

我得到一个带有 filter() 的 Django 查询集

c_layer_points = models.layer_points.objects.filter(location_id=c_location.pk,season_id=c_season.pk,line_path_id=c_line_path.pk,radar_id=c_radar.pk,layer_id__in=c_layer_pks,gps_time__gte=start_gps,gps_time__lte=stop_gps)

这个查询集可能非常大(数十万行)。

现在需要进行的是转换为列表和编码为 JSON。

选项(我在搜索中看到的):

    遍历查询集

例子:

gps_time = [lp.gps_time for lp in c_layer_points];
twtt = [lp.twtt for lp in c_layer_points];
    使用 values() 或 values_list() 使用迭代器()

最后,我想将类似以下格式的 json 编码为:

'gps_time':[list of all gps times],'twtt',[list of all twtt]

任何关于最佳方式的提示都会很棒,谢谢!

【问题讨论】:

您为什么不自己进行测量? import datetime; start = datetime.time(); <do your stuff> end = datetime.time(); print(end-start) 我已经并将继续这样做。但是,我想从其他人那里了解一下这里的“最佳实践”。特别是因为从效率的角度来看,其中一些选项几乎相同。 【参考方案1】:

您可能无法从 ORM 获得所需的格式。但是,您可以有效地执行以下操作:

c_layer_points = models.layer_points.objects.filter(
    location_id=c_location.pk,
    season_id=c_season.pk, 
    line_path_id=c_line_path.pk,
    radar_id=c_radar.pk,
    layer_id__in=c_layer_pks,
    gps_time__gte=start_gps, 
    gps_time__lte=stop_gps
).values_list('gps_time', 'twtt')

现在将元组拆分为两个列表:(元组解包)

split_lst = zip(*c_layer_points)    
dict(gps_time=list(split_lst[0]), twtt=list(split_lst[1]))

【讨论】:

请注意,即使使用.values_list()(或.iterator() 或我能说的任何其他内容),django 也会将所有记录读入内存。非常适合 SQL 性能,如果我们谈论的是大行,那么对于内存来说就不那么好了。我的 python 进程使用了​​ > 300 mb 的 RAM。我最终使用Paginator 来循环遍历记录块。内存与速度是一个权衡,我一次确定了 10,000 条记录。【参考方案2】:

我建议您使用遍历查询集并从查询集中逐个元素地符合 json 字典。

通常,Django 的 QuerySet 是惰性的,这意味着它们在被访问时会加载到内存中。如果您加载整个列表:gps_time = [lp.gps_time for lp in c_layer_points],您将在内存中拥有所有这些对象(数千个)。做一个简单的迭代就可以了:

for item in c_layer_points:
    #convert item to json and add it to the
    #json dict.

顺便说一句,在 python 的行尾,您不需要 ; 字符 :)

希望这会有所帮助!

【讨论】:

太好了,我会看看这个。我也知道“;” MATLAB 是我的主要语言(这正在改变!)所以这只是一个肮脏的习惯! 呵呵呵呵去过,我以前用C++、C#编程过;) 我不确定这是否适合我。我实际上需要对数据进行一些操作(这意味着我真的必须将它作为列表加载到内存中)。例如,我必须根据 c_layer_points 中的项目进行一些插值。

以上是关于从 Django Queryset 获取值列表的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Django QuerySet 中获取绝对图像 URL 列表?

Django Admin:获取根据 GET 字符串过滤的 QuerySet,与更改列表中看到的完全一样?

Django Queryset __in 列表中没有值

Django Queryset 获取所有值并首先相关

Django查询集QuerySet及两大特性

查询集 QuerySet