Django和Pandas之间的一个很酷的绑定是能够直接从QuerySet
构建DataFrame
,使用:
queryset = models.A.objects.filter(...).annotate(...)
frame = pd.DataFrame(queryset.values())
只要QuerySet
至少返回一条记录,它就能很好地工作。在QuerySet
级别上操作很有意思,因为在那里我们可以使用所有注解和本机列。
但是这个方法将返回一个完全空的DataFrame
(没有定义列),比如说:
queryset = models.A.objects.filter(id__lt=0).annotate(...)
frame = pd.DataFrame(queryset.values())
DataFrame完全为空:
Empty DataFrame
Columns: []
Index: []
而我们想要的是这样的东西:
Empty DataFrame
Columns: ["id", "key", "prop1", ...]
Index: []
其中保留了列名,以便使该帧能够与其他帧无缝合并。
pandas的方法是在创建DataFrame
时使用columns
开关强制列名。
queryset = models.A.objects.filter(...)
frame = pd.DataFrame(queryset.values(), columns=queryset.get_fields())
不幸的是,get_fields
或类似的对象似乎没有实现,或者乍一看对QuerySet
对象来说并不明显。
我已经知道我可以从QuerySet
中获取exists()
的列名,使用这个脏的:
frame = pd.DataFrame(
queryset.values(),
columns=queryset[0].__dict__.keys()
)
但是,实际上它不会对空的QuerySet
起作用。
我还知道我可以得到模型列如下:
frame = pd.DataFrame(
queryset.values(),
columns=[item.name for item in queryset.model._meta.get_fields()] + [...]
)
但是这样我就错过了QuerySet
创建的所有注解列,或者需要手动编码,这是我们想要避免的。
我有一种感觉,不知何故,QuerySet
可能知道它应该返回的所有列。至少它应该在查询执行之后知道它,因为空的SQL结果集肯定会包含列名和类型。
所以我的问题是如何从Django QuerySet中获取字段名称,即使它是一个空集?
如果构造有点奇怪或复杂,只要它还允许获取注解列名,这就不是问题。
1条答案
按热度按时间mwyxok5s1#
你可以这样尝试:
我在调试
queryset
对象时发现了这个解决方案。它有一个名为query
的属性,指向这个类Query
的示例。在Query
类中,有一个名为annotations
的属性。此属性包含所有注解信息。您可以使用它来获取所有带注解的字段。