Django中高效实现Excel导入导出的完整指南

Django中高效实现Excel导入导出的完整指南

在Web开发中,数据处理是核心环节之一,尤其是在企业级应用中,Excel文件的导入导出功能几乎是标配。Django作为Python最流行的Web框架之一,提供了灵活的方式来实现这一需求。本文将从零开始,带你掌握在Django中实现Excel导入导出的各种方法,并附上代码示例和最佳实践。

1. 准备工作

首先,确保你已安装Django并创建好项目。接下来,我们需要安装处理Excel的库。推荐使用openpyxl(支持.xlsx格式)和pandas(简化数据处理)。安装命令:

pip install openpyxl pandas xlwt xlrd

xlwt用于旧版.xls写入,xlrd用于读取旧版.xls。根据需求选择。

2. 模型设计

假设我们要管理员工信息,创建一个简单的模型:

from django.db import models

class Employee(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    department = models.CharField(max_length=100)
    salary = models.DecimalField(max_digits=10, decimal_places=2)
    hire_date = models.DateField()

    def __str__(self):
        return self.name

执行迁移:python manage.py makemigrationspython manage.py migrate

3. 导出Excel

3.1 使用openpyxl

创建一个视图export_employees

from django.http import HttpResponse
from openpyxl import Workbook
from .models import Employee

def export_employees(request):
    wb = Workbook()
    ws = wb.active
    ws.title = "Employees"
    # 表头
    headers = ['Name', 'Email', 'Department', 'Salary', 'Hire Date']
    ws.append(headers)
    # 数据
    for emp in Employee.objects.all():
        ws.append([emp.name, emp.email, emp.department, str(emp.salary), emp.hire_date.strftime('%Y-%m-%d')])
    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response['Content-Disposition'] = 'attachment; filename=employees.xlsx'
    wb.save(response)
    return response

3.2 使用pandas简化

pandas可以更简洁地处理DataFrame:

import pandas as pd
from django.http import HttpResponse
from .models import Employee

def export_employees_pandas(request):
    queryset = Employee.objects.all().values('name', 'email', 'department', 'salary', 'hire_date')
    df = pd.DataFrame.from_records(queryset)
    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response['Content-Disposition'] = 'attachment; filename=employees.xlsx'
    with pd.ExcelWriter(response, engine='openpyxl') as writer:
        df.to_excel(writer, index=False, sheet_name='Employees')
    return response

4. 导入Excel

4.1 使用openpyxl

创建一个导入视图:

from django.shortcuts import render, redirect
from openpyxl import load_workbook
from .models import Employee
from datetime import datetime

def import_employees(request):
    if request.method == 'POST' and request.FILES.get('file'):
        file = request.FILES['file']
        wb = load_workbook(file)
        ws = wb.active
        for row in ws.iter_rows(min_row=2, values_only=True):
            name, email, department, salary_str, hire_date_str = row
            # 处理数据类型
            salary = float(salary_str) if salary_str else 0
            hire_date = datetime.strptime(hire_date_str, '%Y-%m-%d').date()
            Employee.objects.create(
                name=name,
                email=email,
                department=department,
                salary=salary,
                hire_date=hire_date
            )
        return redirect('employee_list')
    return render(request, 'import.html')

4.2 使用pandas

更简洁的批量导入:

import pandas as pd
from django.shortcuts import redirect
from .models import Employee

def import_employees_pandas(request):
    if request.method == 'POST' and request.FILES.get('file'):
        file = request.FILES['file']
        df = pd.read_excel(file, engine='openpyxl')
        # 将DataFrame转换为字典列表
        records = df.to_dict('records')
        # 批量创建,注意日期格式
        for record in records:
            Employee.objects.create(
                name=record['Name'],
                email=record['Email'],
                department=record['Department'],
                salary=record['Salary'],
                hire_date=pd.to_datetime(record['Hire Date']).date()
            )
        return redirect('employee_list')
    return render(request, 'import.html')

5. 配置URL和模板

urls.py中添加路径:

from django.urls import path
from . import views

urlpatterns = [
    path('export/', views.export_employees, name='export_employees'),
    path('import/', views.import_employees, name='import_employees'),
]

简单的导入模板import.html

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="file" accept=".xlsx, .xls">
    <button type="submit">导入</button>
</form>

6. 最佳实践与注意事项

  • 数据验证:在导入时务必进行数据清洗和验证,避免脏数据入库。可以使用Django的表单验证或pandas的dropna等方法。
  • 大文件处理:对于超大Excel文件(>500MB),建议使用openpyxl的只读模式或分块读取,避免内存溢出。pandas也可以使用chunksize参数。
  • 事务管理:批量导入时建议使用transaction.atomic包裹,确保数据一致性。
  • 性能优化:当数据量巨大时,使用bulk_create代替逐条创建,可大幅提升性能。
  • 错误处理:提供友好的错误提示,可以用Django messages或返回值告知用户哪些行导入失败。

7. 总结

本文介绍了在Django中实现Excel导入导出的两种主流方法:直接使用openpyxl和借助pandas。前者更加灵活,适合精细控制;后者代码简洁,适合快速开发。根据实际需求选择合适的方案即可。希望本指南能帮助你高效完成任务。

Happy Coding!