Django后台数据导出编码问题处理
最近在为公司项目开发数据导出功能时,遇到了一个令人头疼的编码问题。项目使用Django 3.2框架,后台管理系统需要将数据库中的数据导出为CSV文件。
问题复现步骤
- 在Django admin中创建了一个简单的导出按钮,点击后调用自定义的export_view函数
- 使用Python内置的csv模块写入数据
- 导出的CSV文件在Windows系统下打开时出现乱码
- Mac系统下虽然能正常显示,但中文字符会变成问号
核心代码问题
最初使用的代码如下:
import csv
from django.http import HttpResponse
def export_data(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="data.csv"'
writer = csv.writer(response)
writer.writerow(['姓名', '年龄', '邮箱'])
writer.writerow(['张三', 25, 'zhangsan@example.com'])
return response
解决方案
经过排查,问题出在字符编码上。主要解决方案是:
- 使用UTF-8 BOM编码格式:
response = HttpResponse(content_type='text/csv; charset=utf-8')
response['Content-Disposition'] = 'attachment; filename="data.csv"'
response.write(codecs.BOM_UTF8) # 添加BOM头
- 或者使用Django的FileResponse配合编码参数:
from django.http import FileResponse
import io
output = io.StringIO()
writer = csv.writer(output, quoting=csv.QUOTE_ALL)
writer.writerow(['姓名', '年龄', '邮箱'])
writer.writerow(['张三', 25, 'zhangsan@example.com'])
response = FileResponse(io.BytesIO(output.getvalue().encode('utf-8')), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="data.csv"'
return response
最终推荐方案
考虑到兼容性,建议使用以下完整解决方案:
import csv
import codecs
from django.http import HttpResponse
def export_data(request):
response = HttpResponse(content_type='text/csv; charset=utf-8')
response['Content-Disposition'] = 'attachment; filename="data.csv"'
# 添加UTF-8 BOM头以确保Excel正确识别编码
response.write(codecs.BOM_UTF8)
writer = csv.writer(response)
writer.writerow(['姓名', '年龄', '邮箱'])
writer.writerow(['张三', 25, 'zhangsan@example.com'])
return response
这个方案在Windows和Mac系统下都能完美显示中文内容,避免了编码问题导致的数据混乱。

讨论