上传文档时如何使用Post-save Signal,实现修改文档前后保存并返回下载
功能实现与代码修复
你需要的上传保存、pandas处理、结果保存、返回下载的功能可以通过调整原代码逻辑直接实现,原代码核心问题如下:
pd.read_excel直接传入Document模型实例,没有取实际的文件路径,无法读取上传的Excel内容- 输出文件名拼接时直接拼接模型实例,会得到对象内存地址而非实际文件名,路径错误
- 逻辑嵌套错误,在sheet循环内重复定义
ExcelWriter和BytesIO,还提前return,处理逻辑没有执行完成 - 调用不存在的
newdoc.to_excel方法,应该输出处理后的df而非模型实例
修复后的完整代码
import io import pandas as pd from django.shortcuts import render, redirect from django.http import HttpResponse from .forms import DocumentForm from .models import Document def my_view(request): message = 'Upload as many files as you want!' if request.method == 'POST': form = DocumentForm(request.POST, request.FILES) if form.is_valid(): # 保存上传的源文件 newdoc = Document(docfile=request.FILES['docfile']) newdoc.save() # 1. 读取上传的Excel文件 # 取源文件的实际本地路径 source_file_path = newdoc.docfile.path dfs = pd.read_excel(source_file_path, sheet_name=None) # 2. 内存中生成处理后的Excel output = io.BytesIO() with pd.ExcelWriter(output, engine='xlsxwriter') as writer: for sheet_name, df in dfs.items(): # 执行自定义计算逻辑 df['d'] = df['column1'] / df['column2'] df['e'] = df['column1'] / df['d'] # 写入内存的Excel df.to_excel(writer, sheet_name=sheet_name, index=False) # 指针回到起始位置 output.seek(0) # 3. 可选:将处理后的结果保存到服务器本地(如果需要持久化存储) output_file_name = f'output_{newdoc.docfile.name}' with open(output_file_name, 'wb') as f: f.write(output.getvalue()) # 如果需要把处理后的文件也存入Document模型,可以新增字段后在这里保存 # 4. 返回下载响应 response = HttpResponse( output, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) response['Content-Disposition'] = f'attachment; filename=processed_{newdoc.docfile.name}' return response else: message = 'The form is not valid. Fix the following error:' else: form = DocumentForm() documents = Document.objects.all() context = {'documents': documents, 'form': form, 'message': message} return render(request, 'list.html', context) def results(request): documents = Document.objects.all() context = {'documents': documents} return render(request, 'results.html', context)
注意事项
- 需要确保你上传的Excel里确实存在
column1和column2两个字段,否则计算逻辑会报错,可以根据你的实际字段名修改 - 如果不需要持久化保存处理后的文件,可以删除第三步的本地保存代码
- 大文件处理建议改成异步任务,避免接口超时
内容的提问来源于stack exchange,提问作者project.py
相关产品推荐
相关产品推荐

