Django 和 Pandas 之间的一个很酷的结合是能够直接从
DataFrame
构建一个 QuerySet
使用:
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 结果集肯定会包含列名和类型。
所以我的问题是:How to get fields name from Django QuerySet, even when it's an empty set?
如果结构有点奇怪或令人费解,这不是问题,只要它也允许获取注释列名称。
我认为您已经探索了从 Django 获取字段名称的所有可能选项。您必须记住,
Queryset
本身不是模型字段的表示,而不是数据库中的数据。因此,您将从模型类或模型(对象)的实例而不是查询集中获取模型字段。因此,最简单的方法是定义您想要获取的字段,然后在将其传递给 Pandas DataFrame 之前将其用于 queryset.values()
的值查询集。像这样:
# you are annotating the fields, hence you already know the names of the fields
fields = [item.name for item in queryset.model._meta.get_fields()] + [...]
frame = pd.DataFrame(
queryset.values(*fields),
columns=fields
)