
本教程详细介绍了如何在django项目中实现excel文件数据批量导入到模型表的功能。我们将利用`openpyxl`库解析上传的excel文件,并通过django视图逐行读取数据并创建对应的模型实例,从而简化大量数据的录入过程。
在企业级应用开发中,批量导入数据是常见的需求,尤其是在需要初始化大量数据或定期更新数据时。手动录入数据效率低下且容易出错,而通过导入Excel文件可以大大提高工作效率。本教程将指导您如何在Django框架中,利用openpyxl库实现将Excel数据高效导入到数据库模型表的功能。
首先,您需要安装openpyxl库,它是Python中用于读写Excel .xlsx 文件的强大工具。
pip install openpyxl
为了演示数据导入,我们使用一个简单的Product模型来存储计算机信息。请确保您的models.py中包含以下模型定义:
# your_app_name/models.py
from django.db import models
from django.utils import timezone
class Product(models.Model):
model = models.CharField(max_length=50, null=True, verbose_name="型号")
serial = models.CharField(max_length=50, null=True, unique=True, verbose_name="序列号") # 建议序列号唯一
hd_size = models.CharField(max_length=50, null=True, verbose_name="硬盘大小")
ram = models.CharField(max_length=50, null=True, verbose_name="内存")
processor = models.CharField(max_length=50, null=True, verbose_name="处理器")
date_created = models.DateTimeField(default=timezone.now, verbose_name="创建日期")
date_updated = models.DateTimeField(auto_now=True, verbose_name="更新日期")
class Meta:
verbose_name = "产品"
verbose_name_plural = "产品列表"
def __str__(self):
return f"{self.serial} - {self.model}"注意: 为了数据完整性,我们建议将serial字段设置为unique=True。如果Excel文件中存在重复的序列号,导入时可能会导致错误或需要额外的冲突处理逻辑。
我们需要一个HTML表单来允许用户上传Excel文件。创建一个名为 import_product.html 的模板文件。
<!-- your_app_name/templates/import_product.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>导入产品数据</title>
<style>
body { font-family: sans-serif; background-color: #333; color: whitesmoke; }
.container { max-width: 600px; margin: 50px auto; padding: 20px; border-radius: 8px; background-color: #444; }
form { display: flex; flex-direction: column; gap: 15px; }
input[type="file"] { padding: 10px; border: 1px solid #555; border-radius: 4px; background-color: #666; color: whitesmoke; }
button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
button:hover { background-color: #0056b3; }
.go-back-btn { margin-top: 20px; background-color: #6c757d; }
.go-back-btn:hover { background-color: #5a6268; }
</style>
</head>
<body>
<div class="container">
<p style="font-size:20px;">
选择一个包含您要导入的产品数据的Excel文件
</p>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="excel_file" accept=".xlsx, .xls">
<button type="submit">导入</button>
</form>
<div class="container-fluid">
<button class="go-back-btn" onclick="goBack()">返回</button>
</div>
</div>
<script>
function goBack() {
window.history.back();
}
</script>
</body>
</html>关键点:
接下来,在您的views.py中创建处理文件上传和数据导入的视图函数。
# your_app_name/views.py
import openpyxl
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import Product # 导入您的Product模型
@login_required
def import_product(request):
"""
处理Excel文件上传并导入产品数据到数据库。
"""
if request.method == 'POST':
if 'excel_file' in request.FILES:
excel_file = request.FILES['excel_file']
# 检查文件类型,确保是Excel文件
if not excel_file.name.endswith(('.xlsx', '.xls')):
# 可以添加错误消息到前端
return render(request, 'import_product.html', {'error_message': '请上传有效的Excel文件 (.xlsx 或 .xls)。'})
try:
wb = openpyxl.load_workbook(excel_file)
ws = wb.active # 获取活动工作表
# 存储要创建的Product对象列表
products_to_create = []
# 遍历工作表中的每一行,从第二行开始 (跳过标题行)
# values_only=True 表示只获取单元格的值,而不是单元格对象
for row_num, row in enumerate(ws.iter_rows(min_row=2, values_only=True), start=2):
# 确保行数据长度与模型字段匹配
if len(row) < 5: # model, serial, hd_size, ram, processor
# 记录错误或跳过此行
print(f"警告: 第 {row_num} 行数据不完整,已跳过: {row}")
continue
# 解包行数据到对应的变量
# 确保Excel列的顺序与这里解包的变量顺序一致
model_val, serial_val, hd_size_val, ram_val, processor_val = row[:5]
# 简单的非空验证
if not all([model_val, serial_val, hd_size_val, ram_val, processor_val]):
print(f"警告: 第 {row_num} 行存在空值,已跳过: {row}")
continue
# 创建Product对象,但不立即保存
product = Product(
model=str(model_val).strip() if model_val is not None else '',
serial=str(serial_val).strip() if serial_val is not None else '',
hd_size=str(hd_size_val).strip() if hd_size_val is not None else '',
ram=str(ram_val).strip() if ram_val is not None else '',
processor=str(processor_val).strip() if processor_val is not None else '',
)
products_to_create.append(product)
# 使用 bulk_create 批量创建对象,提高性能
Product.objects.bulk_create(products_to_create, ignore_conflicts=True) # ignore_conflicts=True 忽略重复的serial
return redirect('import_success_2') # 导入成功后重定向到成功页面
except Exception as e:
# 捕获处理Excel文件或数据库操作中的任何异常
print(f"导入过程中发生错误: {e}")
return render(request, 'import_product.html', {'error_message': f'导入失败: {e}'})
else:
return render(request, 'import_product.html', {'error_message': '请选择一个文件进行上传。'})
return render(request, 'import_product.html')
@login_required
def import_success_2(request):
"""
导入成功后的显示页面。
"""
return render(request, 'your_app_name/import_success_2.html') # 确保路径正确代码解析:
创建一个简单的 import_success_2.html 模板,用于显示导入成功的消息。
<!-- your_app_name/templates/your_app_name/import_success_2.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>导入成功</title>
<style>
body { font-family: sans-serif; background-color: #333; color: whitesmoke; text-align: center; }
.container { max-width: 600px; margin: 50px auto; padding: 20px; border-radius: 8px; background-color: #444; }
h1 { color: #28a745; }
button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; margin-top: 20px; }
button:hover { background-color: #0056b3; }
</style>
</head>
<body>
<div class="container">
<h1>数据导入成功!</h1>
<p>您的Excel文件已成功导入到数据库中。</p>
<button onclick="window.location.href='/'">返回首页</button> <!-- 或其他页面 -->
</div>
</body>
</html>最后,您需要在项目的urls.py中配置相应的URL路由,将URL模式映射到视图函数。
# your_project_name/urls.py 或 your_app_name/urls.py
from django.contrib import admin
from django.urls import path
from your_app_name import views # 假设您的应用名为 your_app_name
urlpatterns = [
path('admin/', admin.site.urls),
path('import/product/', views.import_product, name='import_product'),
path('import/success/', views.import_success_2, name='import_success_2'),
# ... 其他URL配置
]在将数据保存到数据库之前,进行严格的数据验证至关重要。
# your_app_name/forms.py
from django import forms
from .models import Product
class ProductImportForm(forms.ModelForm):
class Meta:
model = Product
fields = ['model', 'serial', 'hd_size', 'ram', 'processor']
def clean_serial(self):
serial = self.cleaned_data['serial']
if Product.objects.filter(serial=serial).exists():
raise forms.ValidationError(f"序列号 '{serial}' 已存在。")
return serial
# 在 views.py 中使用
# ...
# for row_num, row in enumerate(ws.iter_rows(min_row=2, values_only=True), start=2):
# # ... 解包数据
# data = {
# 'model': model_val, 'serial': serial_val, 'hd_size': hd_size_val,
# 'ram': ram_val, 'processor': processor_val
# }
# form = ProductImportForm(data)
# if form.is_valid():
# product = form.save(commit=False) # 不立即保存
# products_to_create.append(product)
# else:
# # 处理验证失败的行,例如记录错误或返回给用户
# print(f"第 {row_num} 行数据验证失败: {form.errors}")
# ...# 在 views.py 中使用事务
from django.db import transaction
# ...
# @login_required
# def import_product(request):
# # ...
# if request.method == 'POST':
# # ...
# try:
# with transaction.atomic(): # 确保所有操作在一个事务中
# # ... openpyxl 加载和遍历
# # ... products_to_create 列表填充
# Product.objects.bulk_create(products_to_create, ignore_conflicts=True)
# return redirect('import_success_2')
# except Exception as e:
# # 事务失败会自动回滚
# print(f"导入过程中发生错误: {e}")
# return render(request, 'import_product.html', {'error_message': f'导入失败: {e}'})
# # ...通过本教程,您应该已经掌握了在Django项目中实现Excel文件批量导入到模型表的基本方法。我们利用openpyxl库解析Excel文件,结合Django视图和模型操作,实现了高效的数据录入。同时,我们也探讨了数据验证、错误处理、事务管理和性能优化等进阶主题,帮助您构建更加健壮和用户友好的导入功能。在实际项目中,请根据您的具体需求和数据规模,选择最适合的实现策略。
以上就是在Django应用中高效导入Excel数据到模型表:完整教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号