从 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 列表?