找回密码
 立即注册
首页 业界区 业界 Django实战:基于Django和openpyxl实现Excel导入导出功 ...

Django实战:基于Django和openpyxl实现Excel导入导出功能

箝德孜 9 小时前
一、openpyxl 介绍

openpyxl 是一个用于读取和写入 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。使用场景包括:

  • 数据分析:从 Excel 文件中读取数据,进行处理和分析。
  • 自动化办公:自动生成报告、填写表格等。
  • 数据导入导出:将数据从 Python 程序导入到 Excel,或将 Excel 数据导入到 Python 程序中。
安装openpyxl
  1. pip install openpyxl
复制代码
二、Excel文件下载

创建并保存 Excel 文件

示例:创建一个新的 Excel 工作簿,并写入一些数据,最后保存为文件
  1. from openpyxl import Workbook
  2. # 创建一个新的工作簿
  3. workbook = Workbook()
  4. # 获取默认的工作表
  5. sheet = workbook.active
  6. sheet.title = "MySheet"  # 设置工作表标题
  7. # 写入数据到单元格
  8. sheet['A1'] = "Hello, Openpyxl!"
  9. sheet['B2'] = 42
  10. # 保存工作簿
  11. workbook.save('new_example.xlsx')
复制代码
Excel工具函数

为提高代码复用率,整理处理Excel工具函数

  • create_excel_workbook():将数据 data 按照指定字段和标签写入一个新的 Excel 工作簿,并设置表头和列宽。
  • generate_excel_response():将 workbook(Excel 工作簿)生成 Excel 文件,并通过 HTTP 响应返回给客户端下载
  • process_item():将一个数据项 item 按照指定字段顺序 fields 转换为一行数据(列表)
  • convert_datetime():将带有时区信息的 ISO 格式时间字符串(如 "2023-01-01T12:34:56.789+08:00")转换为去除时区、毫秒并替换 T 为空格的字符串,输出格式为 "YYYY-MM-DD HH:MM:SS"。
  1. from urllib.parse import quote
  2. from django.http import HttpResponse
  3. from openpyxl import Workbook
  4. from openpyxl.utils import get_column_letter
  5. def convert_datetime(datetime_str):
  6.     # 移除时区部分(+08:00)
  7.     datetime_without_tz = datetime_str.replace("+08:00", "")
  8.     # 移除 "T" 并截取到秒部分(去掉毫秒)
  9.     return datetime_without_tz.replace("T", " ").split(".")[0]
  10. def process_item(item, fields, data_map={}):
  11.     """将单个数据项转换为行数据"""
  12.     row = []
  13.     for field in fields:
  14.         value = item.get(field)
  15.         # 友好显示转换
  16.         if field in data_map:
  17.             value = data_map[field].get(value, None)
  18.         # 特殊字段类型转换
  19.         elif field == "id" or field == "job_id":
  20.             value = str(value)
  21.         elif field == "create_time" or field == "date_created" or field == "date_done":
  22.             value = convert_datetime(value)
  23.         row.append(value)
  24.     return row
  25. def create_excel_workbook(data, fields_labels, data_map={}, sheet_name="Sheet1"):
  26.     """
  27.     将数据写入Excel文件
  28.     """
  29.     fields = list(fields_labels.keys())
  30.     labels = list(fields_labels.values())
  31.     # 创建一个 Excel 工作簿
  32.     workbook = Workbook()
  33.     sheet = workbook.active
  34.     sheet.title = sheet_name
  35.     # 设置表头
  36.     sheet.append(labels)
  37.     # 添加数据
  38.     for item in data:
  39.         row = process_item(item, fields, data_map)
  40.         sheet.append(row)
  41.     # 设置列宽
  42.     for col_num in range(1, len(labels) + 1):
  43.         col_letter = get_column_letter(col_num)
  44.         sheet.column_dimensions[col_letter].width = 15
  45.     return workbook
  46. def generate_excel_response(workbook, file_name="export.xlsx"):
  47.     """
  48.     生成 Excel 文件并返回 HTTP 响应。
  49.     """
  50.     response = HttpResponse(
  51.         content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  52.     )
  53.     response["Content-Disposition"] = f"attachment; filename={quote(file_name)}"
  54.     workbook.save(response)
  55.     return response
复制代码
点击查看完整代码
项目实战:Excel文件下载

实战场景:在Django+Vue3后台管理系统中,实现用户的导入导出功能是常见需求。用户导入功能,一般需要先下载模板,填写后再导入。
1.png

实战代码:定义视图,将示例数据导出为 Excel 文件并返回给用户下载,实现下载模板功能
  1.   @extend_schema(summary="获得用户导入模板")
  2.     @action(
  3.         methods=["get"],
  4.         detail=False,
  5.         url_path="get-import-template",
  6.     )
  7.     def get_import_template(self, request, *args, **kwargs):
  8.         """获得用户导入模板"""
  9.         # 定义示例数据
  10.         data = [
  11.             {
  12.                 "username": "xiaozhang",
  13.                 "nickname": "小张",
  14.                 "deptId": "103",
  15.                 "email": "xz@qq.com",
  16.                 "mobile": "13312345670",
  17.                 "sex": "男",
  18.                 "status": "开启",
  19.             },
  20.             {
  21.                 "username": "xiaoli",
  22.                 "nickname": "小李",
  23.                 "deptId": "",
  24.                 "email": "",
  25.                 "mobile": "",
  26.                 "sex": "",
  27.                 "status": "关闭",
  28.             },
  29.         ]
  30.         fields_labels = {
  31.             "username": "用户账号",
  32.             "nickname": "用户昵称",
  33.             "deptId": "部门编号",
  34.             "email": "用户邮箱",
  35.             "mobile": "手机号码",
  36.             "sex": "用户性别",
  37.             "status": "账号状态",
  38.         }
  39.         # 返回工作簿
  40.         workbook = create_excel_workbook(data, fields_labels)
  41.         return generate_excel_response(workbook, "用户导入模板.xlsx")
复制代码
实现效果
2.png

三、Excel 文件上传

获取上传的文件

当 Django 处理文件上传时,文件数据会被放置在 request.FILES 中。获取上传文件示例
  1. file = request.FILES.get("file")
复制代码
读取Excel中的数据

示例:读取example.xlsx文件中的标题、单元格等信息
  1. from openpyxl import load_workbook
  2. # 加载一个已存在的Excel文件
  3. workbook = load_workbook('example.xlsx')
  4. # 获取工作簿中的工作表
  5. sheet = workbook.active  # 获取当前活动的工作表
  6. print(sheet.title)  # 输出工作表的标题
  7. # 读取单元格的值
  8. cell_value = sheet['A1'].value
  9. print(cell_value)
复制代码
项目实战:Excel文件上传

实战场景:在Django+Vue3后台管理系统中,实现用户导入功能

  • 第一步:获取用户上传的文件
  • 第二步:调用get_user_import_data()函数,读取Excel文件中的用户数据,并将其转换为系统所需格式的字典列表。
  • 第三步:使用序列化器,将用户信息保存到数据库
3.png
  1. def get_user_import_data(file) -> list:
  2.     """
  3.     读取Excel文件中的用户信息,并将其转换为字典列表
  4.     """
  5.     # 加载Excel文件
  6.     workbook = load_workbook(file)
  7.     sheet = workbook.active
  8.     # 固定表头,以确保数据字段的一致性
  9.     headers = ["username", "nickname", "deptId", "email", "mobile", "sex", "status"]
  10.     # 初始化数据列表
  11.     data = []
  12.     # 遍历每一行数据
  13.     for row in sheet.iter_rows(min_row=2, values_only=True):
  14.         # 将当前行数据与表头 zip 后转换为字典
  15.         user_data = dict(zip(headers, row))
  16.         # 转换 sex 和 status 字段
  17.         user_data["sex"] = (
  18.             1 if user_data["sex"] == "男" else 2 if user_data["sex"] == "女" else 0
  19.         )
  20.         user_data["status"] = (
  21.             0
  22.             if user_data["status"] == "开启"
  23.             else 1 if user_data["status"] == "关闭" else None
  24.         )
  25.         data.append(user_data)
  26.     return data
复制代码
实现效果:点击查看完整代码
4.png

您正在阅读的是《Django从入门到实战》专栏!关注不迷路~

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册