格式化Django QuerySet以将值输出为数组

时间:2017-10-13 22:52:19

标签: python django django-queryset django-postgresql

我的表中的数据如下所示:

src_id, dst_id, params
int   , int   , array

我查询数据以从数组中提取一些值 使用以下Django查询

dataset = query_set.values_list('src_id', 'dst_id', *[e.field for e in settings])

我需要输出这样的数据:

[
[1,2,[a,b,c,d]],
[3,4,[a,c,d,e]],
...
]

但是values_list返回一个像元组的列表 (1,2,a,b,c,d)(3,4,a,c,d,e)...

所以我一直在做以下操作,将元组值重新组合成一个数组:

[[d[0], d[1], d[2:]] for d in dataset]

它工作正常,但我有1M +行,而且速度很慢。它也使用了大量的内存。理想情况下,我想在SQL中正确格式化数据(通过Django),并将输出直接推送到JSON序列化程序,而不必生成中间数组。

有没有办法优化此代码?

我看过使用循环或lambda,但这并没有太大的区别。我查看了使用array,但它只采用了原始类型,因此数组数组没有多少运气。

我正在寻找一种查询数据库的方法,并以正确的格式直接输出数据,如果可能的话,在Django中:

我看到Django可以像

一样进行切片数组查找

dataset = query_set.values_list('src_id', 'dst_id', 'data__3_10')

例如,

获取索引3和10之间的值,但我需要检索特定的索引(例如1,4,5,6,8,11),而不是切片。

有关如何格式化这样的查询输出的任何提示? Django有可能,或者只是太深奥了吗? 我需要raw SQL吗?

由于

2 个答案:

答案 0 :(得分:2)

如果数据库是 PostgreSQL Oracle ,那么 Django 1.11 的内存要求可以通过iterator()方法应用到任何查询集,包括android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.values()查询集。然后默认情况下使用服务器端游标,而不在Django或数据库驱动程序中进行任何缓存。阅读文档中的详细信息。

演示

values_list()

输出

qs = query_set.values_list('src_id', 'dst_id', 'data')
for row in qs.iterator():
    print(row) 

完整示例

(3, 4, ['a', 'c', 'd', 'e'])
...

内存要求可以忽略不计。

答案 1 :(得分:1)

我能够使用extra()功能直接在Django中格式化输出而无需使用原始SQL:

dataset = queryset.objects\
               .extra(select={'data': 'ARRAY[{}]'.format(",".join([fields])})\
               .values_list('src_id','dst_id','data')
return dataset.iterator()

这允许我根据需要选择SQL数组中的特定索引。

返回迭代器(由@hynekcer建议),而不是结果数组本身,实际上更适合内存。

避免循环重新格式化数据,迭代器可以直接发送到JSON序列化程序,它接受迭代器作为输入。