You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Django导出模型数据到Excel时遇TypeError: expected <class 'float'>错误求助

解决TypeError: expected <class 'float'>错误(Django模型导出Excel)

我一眼就瞅出问题出在你设置列宽的代码上!咱们一步步拆解分析:

错误根源

你定义的columns是纯字段名字符串列表:

columns=['Id','Name','Image1','Image2','Date']

然后你写了这么一行代码:

ws.column_dimensions[get_column_letter(col_num + 1)].width = columns[col_num][1]

这里的columns[col_num][1]是取每个字段名的第二个字符(比如'Id'[1]就是'd'),这是个字符串类型,但openpyxl要求列宽必须是浮点数(float),直接赋值字符串自然就抛出了TypeError: expected <class 'float'>

顺带提一句,你设置表头的代码c.value = columns[col_num][0]也有问题——这会把表头变成每个字段名的第一个字符(比如Name变成'N'),显然不是你想要的效果。

修复方案

你需要把字段名和对应列宽分开定义,用元组列表存储(每个元组存「字段名,列宽」),然后分别赋值:

核心代码修改

# 定义字段名+对应列宽的元组列表,列宽设置为你需要的浮点数
columns = [('Id', 10.0), ('Name', 20.0), ('Image1', 30.0), ('Image2', 30.0), ('Date', 15.0)]

row_num = 0
for col_num in range(len(columns)):
    c = ws.cell(row=row_num + 1, column=col_num + 1)
    # 设置完整字段名为表头
    c.value = columns[col_num][0]
    # 用浮点数设置列宽
    ws.column_dimensions[get_column_letter(col_num + 1)].width = columns[col_num][1]

另外还有个小细节:你设置下载文件名的代码没闭合引号,要改成:

response['Content-Disposition'] = 'attachment; filename="users.xls"'

额外优化建议

  • 直接导出obj.Image1(FileField对象)的话,Excel里会显示类似<FieldFile: media/images/xxx.jpg>的字符串,如果你想显示文件路径或URL,可以改成obj.Image1.path(本地路径)或obj.Image1.url(访问URL),记得处理空值情况;
  • 日期字段obj.Date会被openpyxl自动转为Excel日期格式,空值也会正常显示为空单元格,这部分没问题。

完整修正后的list方法代码

def list(self,request):
    try:
        queryset=Task.objects.all()
        response = HttpResponse(content_type='application/ms-excel')
        # 修复文件名引号闭合问题
        response['Content-Disposition'] = 'attachment; filename="users.xls"'
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "Your Title"
        row_num=0
        # 字段名+列宽的元组列表
        columns = [('Id', 10.0), ('Name', 20.0), ('Image1', 30.0), ('Image2', 30.0), ('Date', 15.0)]
        for col_num in range(len(columns)):
            c = ws.cell(row=row_num + 1, column=col_num + 1)
            c.value = columns[col_num][0]
            ws.column_dimensions[get_column_letter(col_num + 1)].width = columns[col_num][1]
        for obj in queryset:
            row_num += 1
            # 优化FileField显示内容,示例用URL,可按需换成path
            row = [ 
                obj.Id, 
                obj.Name, 
                obj.Image1.url if obj.Image1 else "", 
                obj.Image2.url if obj.Image2 else "", 
                obj.Date, 
            ]
            for col_num in range(len(row)):
                c = ws.cell(row=row_num + 1, column=col_num + 1)
                c.value = row[col_num]
        wb.save(response)
        return response
    except Exception as error:
        traceback.print_exc()
        return Response({"message": str(error), "success": False}, status=status.HTTP_200_OK)

这样修改后,你的导出功能就能正常运行啦!

内容的提问来源于stack exchange,提问作者Ashuosh Mishra

火山引擎 最新活动