在django中使用pandas操作django的ORM查询出来的QuerySet对象,可以使用插件django-pandas。
截止教程书写时间,django-pandas已发布到0.6.1。
依赖:django>=1.4.5
Django-model-utils >=1.4.0
Pandas >=0.12.0
当然,还需要numpy
用法:
1、IO模块:
该django-pandas.io模块提供了一些方便的方法,以便从django的查询集转换成DataFrames的创建。
read_frame
参数:
l qs :一个django的QuerySet。
l fieldnames :用于创建DataFrame的模型字段名称列表。可以使用双下划线指定另一个model中的相关字段,以通常的Django方式跨越关系。
l index_col:使用指定用于DataFrame索引的字段名称。如果索引字段不在fieldnames参数中,则将会添加,注意这里的字段必须为该model里的字段。
l coerce_float:Boolean(布尔值),默认为True。尝试将值转换为非字符串,将非数字对象(如decimal.Decimal)转化为浮点类型。
Eg:
model.py
class Img_info(models.Model): ''' 图片信息表 ''' img_name = models.CharField(max_length=128, verbose_name="图片名") img = models.ImageField(upload_to="img", verbose_name="图片") class Meta: db_table = "img_info" class Product_score(models.Model): ''' 图片打分表 ''' img_of = models.ForeignKey(Img_info, on_delete=models.CASCADE, verbose_name="图片") scoring_staff = models.CharField(max_length=32, verbose_name="打分员") score_num = models.FloatField(verbose_name="分数") class Meta: db_table = "product_score"
views.py
1、直接转化
from django_pandas.io import read_frame def tset(request): qs = Product_score.objects.all() qs_dataframe = read_frame(qs=qs) print(qs_dataframe) return HttpResponse('ok')
运行结果:
id img_of scoring_staff score_num
0 15 Img_info object (5) 测试1 22.0
1 16 Img_info object (6) 测试1 23.0
2 17 Img_info object (7) 测试1 24.0
3 18 Img_info object (8) 测试1 25.0
4 19 Img_info object (9) 测试1 26.0
5 20 Img_info object (5) 测试2 22.0
6 21 Img_info object (6) 测试2 23.0
7 22 Img_info object (7) 测试2 24.0
8 23 Img_info object (8) 测试2 25.0
9 24 Img_info object (9) 测试2 26.0
10 25 Img_info object (5) 测试3 22.0
11 26 Img_info object (6) 测试3 23.0
12 27 Img_info object (7) 测试3 24.0
13 28 Img_info object (8) 测试3 25.0
2、跨关联表显示
views.py
from django_pandas.io import read_frame def tset(request): qs = Product_score.objects.all() qs_dataframe = read_frame(qs=qs,fieldnames=['img_of__img_name', 'scoring_staff', 'score_num']) print(qs_dataframe) return HttpResponse('ok')
运行结果:
img_of__img_name scoring_staff score_num
0 士大夫 测试1 22.0
1 士大夫 测试2 22.0
2 士大夫 测试3 22.0
3 54撒 测试1 23.0
4 54撒 测试2 23.0
5 54撒 测试3 23.0
6 撒旦撒 测试1 24.0
7 撒旦撒 测试2 24.0
8 撒旦撒 测试3 24.0
9 撒旦撒2 测试1 25.0
10 撒旦撒2 测试2 25.0
11 撒旦撒2 测试3 25.0
12 24 测试1 26.0
13 24 测试2 26.0
3、指定索引
views.py
def tset(request): qs = Product_score.objects.all() qs_dataframe = read_frame(qs=qs,fieldnames=['img_of__img_name', 'scoring_staff', 'score_num'],index_col='id') print(qs_dataframe) return HttpResponse('ok')
运行结果:
img_of__img_name scoring_staff score_num
id
15 士大夫 测试1 22.0
20 士大夫 测试2 22.0
25 士大夫 测试3 22.0
16 54撒 测试1 23.0
21 54撒 测试2 23.0
26 54撒 测试3 23.0
17 撒旦撒 测试1 24.0
22 撒旦撒 测试2 24.0
27 撒旦撒 测试3 24.0
18 撒旦撒2 测试1 25.0
23 撒旦撒2 测试2 25.0
28 撒旦撒2 测试3 25.0
19 24 测试1 26.0
24 24 测试2 26.0
2、DataFrameManager
django-pandas提供了一个自定义管理器,可用于要呈现为pandas Dataframes的模型。该DataFrameManager管理器提供to_dataframe返回你模型查询集(queryset )为pandas的DataFrame。要使用DataFrameManager,首先覆盖model定义中的默认管理器(objects)。
这将使您可以访问以下QuerySet方法:
l to_dataframe 从QuerySet返回DataFrame
l to_timeserie 用于创建时间序列的便捷方法,即DataFrame索引是DateTime或PeriodIndex的实例
l to_pivot_table 从QuerySet创建数据透视表的便捷方法
to_dataframe
l fieldnames :用于创建DataFrame的模型字段名称列表。可以使用双下划线指定另一个model中的相关字段,以通常的Django方式跨越关系。
l index:使用指定用于DataFrame索引的字段名称。如果索引字段不在fieldnames参数中,则将会添加,注意这里的字段必须为该model里的字段。
l coerce_float:Boolean(布尔值),默认为True。尝试将值转换为非字符串,将非数字对象(如decimal.Decimal)转化为浮点类型。
eg:
models.py
class Img_info(models.Model): ''' 图片信息表 ''' img_name = models.CharField(max_length=128, verbose_name="图片名") img = models.ImageField(upload_to="img", verbose_name="图片") class Meta: db_table = "img_info" class Product_score(models.Model): ''' 图片打分表 ''' img_of = models.ForeignKey(Img_info, on_delete=models.CASCADE, verbose_name="图片") scoring_staff = models.CharField(max_length=32, verbose_name="打分员") score_num = models.FloatField(verbose_name="分数") objects = DataFrameManager() class Meta: db_table = "product_score"
views.py
def tset(request): qs = Product_score.objects.all() qs_dataframe = qs.to_dataframe(fieldnames=['img_of__img_name', 'scoring_staff', 'score_num'], index='id', coerce_float=True) print(qs_dataframe) return HttpResponse('ok')
运行结果:
img_of__img_name scoring_staff score_num
id
15 士大夫 测试1 22.0
20 士大夫 测试2 22.0
25 士大夫 测试3 22.0
16 54撒 测试1 23.0
21 54撒 测试2 23.0
26 54撒 测试3 23.0
17 撒旦撒 测试1 24.0
22 撒旦撒 测试2 24.0
27 撒旦撒 测试3 24.0
18 撒旦撒2 测试1 25.0
23 撒旦撒2 测试2 25.0
28 撒旦撒2 测试3 25.0
19 24 测试1 26.0
24 24 测试2 26.0
您可以使用过滤器和排除:
筛选出分数大于23的
views.py
def tset(request): qs = Product_score.objects.all() qs_dataframe = qs.filter(score_num__gt=23).to_dataframe(fieldnames=['img_of__img_name', 'scoring_staff', 'score_num'], index='id', coerce_float=True) print(qs_dataframe) return HttpResponse('ok')
运行结果:
img_of__img_name scoring_staff score_num
id
17 撒旦撒 测试1 24.0
18 撒旦撒2 测试1 25.0
19 24 测试1 26.0
22 撒旦撒 测试2 24.0
23 撒旦撒2 测试2 25.0
24 24 测试2 26.0
27 撒旦撒 测试3 24.0
28 撒旦撒2 测试3 25.0
to_pivot_table
-
- fieldnames:用于创建DataFrame的模型字段名称列表。可以使用双下划线指定另一个model中的相关字段,以通常的Django方式跨越关系。
- values:要聚合的列,可选
-
- rows : 要分组的列名称或数组的列表,在数据透视表的x轴上分组的键
-
- cols : 要分组的列名称或数组的列表,在数据透视表的y轴上分组的键
-
- aggfunc : function,默认numpy.mean或函数列表,如果传递的函数列表,生成的数据透视表将具有分层列,其顶层是函数名称(从函数对象本身推断)
-
- fill_value : 标量,默认无,用于替换缺失值的值
-
- margin : boolean,默认为False,添加所有行/列(例如,对于小计/总计)
- dropna:布尔值,默认为True,去除NaN值
views.py
def tset(request): qs = Product_score.objects.all() data_df_to_pivot_table = qs.to_pivot_table( values='score_num', rows=['img_of__img_name'], cols=['scoring_staff'], fieldnames=['img_of__img_name', 'scoring_staff', 'score_num'], margins=True) print(data_df_to_pivot_table) return HttpResponse('ok')
运行结果:
scoring_staff 测试1 测试2 测试3 All img_of__img_name 24 26.0 26.0 NaN 26.000000 54撒 23.0 23.0 23.0 23.000000 士大夫 22.0 22.0 22.0 22.000000 撒旦撒 24.0 24.0 24.0 24.000000 撒旦撒2 25.0 25.0 25.0 25.000000 All 24.0 24.0 23.5 23.857143