修改了excel解析上传
This commit is contained in:
parent
c7b6c57f26
commit
365ad8d2b6
|
@ -2,5 +2,7 @@ from django.urls import path
|
|||
from excel_parser.views import *
|
||||
|
||||
urlpatterns = [
|
||||
path('common_parse/', common_parse, name="common_parse")
|
||||
path('excel_preview/', excel_preview, name='excel_preview'),
|
||||
path('dl_excel_tpl/<str:template_name>/', dl_excel_tpl, name='dl_excel_tpl'),
|
||||
path('common_parse/', common_parse, name="ep_common_parse")
|
||||
]
|
|
@ -1,5 +1,95 @@
|
|||
import urllib.parse
|
||||
from datetime import datetime
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.http import HttpResponseBadRequest, JsonResponse, FileResponse, HttpResponseNotFound
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from openpyxl.reader.excel import load_workbook
|
||||
|
||||
|
||||
@login_required
|
||||
def dl_excel_tpl(request, template_name):
|
||||
"""
|
||||
该视图提供下载指定的Excel模板文件。
|
||||
|
||||
参数:
|
||||
request: HttpRequest对象。
|
||||
template_name: 请求下载的Excel模板文件的名称,期望是一个字符串。
|
||||
fields: 包含字段信息的字典,用于生成Excel文件的表头和格式。
|
||||
|
||||
返回:
|
||||
FileResponse对象,允许用户下载生成的Excel文件。
|
||||
如果文件未找到,则返回一个HttpResponseNotFound响应。
|
||||
"""
|
||||
# 使用finders.find()根据文件名在Django的静态文件目录中查找文件的绝对路径
|
||||
file_path = finders.find(f'excels/{template_name}')
|
||||
|
||||
# 如果文件路径不存在,返回404响应
|
||||
if not file_path:
|
||||
return JsonResponse("Excel模板文件不存在", status=400)
|
||||
|
||||
# 创建FileResponse对象,设置为以附件形式下载,设置MIME类型为Excel文件
|
||||
response = FileResponse(open(file_path, 'rb'), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||
# 设置Content-Disposition头,告诉浏览器这是一个需要下载的文件
|
||||
# 使用urllib.parse.quote对文件名进行URL编码,以确保文件名中包含的特殊字符不会引起问题
|
||||
response['Content-Disposition'] = f'attachment; filename="{urllib.parse.quote(template_name)}"'
|
||||
return response
|
||||
|
||||
|
||||
@login_required
|
||||
def common_parse(request):
|
||||
return render(request, 'excel_preview_table.html')
|
||||
if request.method == 'POST':
|
||||
excel_file = request.FILES['file']
|
||||
template_name = request.POST.get('template_name')
|
||||
|
||||
wb = load_workbook(excel_file)
|
||||
sheet = wb.active
|
||||
|
||||
# 获取上传文件中的列名
|
||||
uploaded_columns = [cell.value for cell in sheet[1]]
|
||||
|
||||
# 获取模板中的列名
|
||||
template_path = finders.find(f'excels/{template_name}')
|
||||
if not template_path:
|
||||
return JsonResponse({'error': "Excel模板文件不存在"}, status=400)
|
||||
|
||||
template_wb = load_workbook(template_path)
|
||||
template_sheet = template_wb.active
|
||||
template_columns = [cell.value for cell in template_sheet[1]]
|
||||
|
||||
# 对比表头
|
||||
if uploaded_columns != template_columns:
|
||||
return JsonResponse({'error': "请使用填报模板上传"}, status=400)
|
||||
|
||||
# 获取数据并处理 datetime 对象
|
||||
data = []
|
||||
for row in sheet.iter_rows(min_row=2, values_only=True):
|
||||
row_data = []
|
||||
for cell in row:
|
||||
if isinstance(cell, datetime):
|
||||
row_data.append(cell.strftime('%Y-%m-%d'))
|
||||
else:
|
||||
row_data.append(cell)
|
||||
|
||||
# 检查行是否有非空单元格
|
||||
if any(cell is not None and cell != '' for cell in row_data):
|
||||
data.append(row_data)
|
||||
|
||||
# 存储解析数据到 session 中
|
||||
request.session['columns'] = uploaded_columns
|
||||
request.session['table_data'] = data
|
||||
|
||||
# 返回新的页面 URL
|
||||
return JsonResponse({'redirect_url': reverse("excel_preview")})
|
||||
else:
|
||||
return JsonResponse({"error": "请求方法错误"}, status=400)
|
||||
|
||||
|
||||
@login_required
|
||||
def excel_preview(request):
|
||||
columns = request.session.get('columns', [])
|
||||
table_data = request.session.get('table_data', [])
|
||||
|
||||
return render(request, 'excel_preview_table.html', {'columns': columns, 'table_data': table_data})
|
||||
|
|
|
@ -71,7 +71,8 @@
|
|||
{% render_button 'modify_records_button' %}
|
||||
{% render_button 'add_button' %}
|
||||
{% render_button 'report_excel_button' %}
|
||||
{% render_button 'import_excel_button' %}
|
||||
{# {% render_button 'import_excel_button' %}#}
|
||||
<button id="importExcelBtnTest" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#uploadModal">上传Excel(测试)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -173,16 +174,56 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="uploadModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="uploadModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<form id="upload-form" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="uploadModalLabel">上传Excel文件</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input id="inputFile" type="file" name="excel_file" class="form-control" hidden accept=".xlsx">
|
||||
<label class="btn btn-outline-primary" for="inputFile">选择文件</label>
|
||||
<span id="file-chosen" style="font-size: 12px; margin-left: 10px;">未选择文件</span>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="downloadExcelBtn" type="button" class="btn btn-secondary" onclick="#!">下载填报模板</button>
|
||||
<button id="uploadBtn" type="button" class="btn btn-primary">上传Excel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'modify_record_modal.html' with modify_records_url=modify_records_url %}
|
||||
{% include 'upload_excel_modal.html' with excel_upload_config=excel_upload_config %}
|
||||
|
||||
<script>
|
||||
const add_url = "{{ add_url }}";
|
||||
const modify_url = "{{ modify_url }}";
|
||||
const deleteUrl = "{{ delete_url }}";
|
||||
let targetIdToDelete = null;
|
||||
var templateName = "{{ excel_upload_config.template_name }}";
|
||||
|
||||
$(document).ready(function () {
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
const csrftoken = getCookie('csrftoken');
|
||||
|
||||
// 处理添加按钮点击事件
|
||||
$('#addItemBtn').click(function () {
|
||||
$.ajax({
|
||||
|
@ -285,6 +326,56 @@
|
|||
$('#deleteModal').modal('hide');
|
||||
}
|
||||
});
|
||||
|
||||
// 点击下载Excel模板按钮
|
||||
$('#downloadExcelBtn').on('click', function () {
|
||||
window.location.href = excel_upload_config.template_url;
|
||||
});
|
||||
|
||||
// 当上传模态框显示时,清空文件输入框和文件名显示
|
||||
$('#uploadModal').on('show.bs.modal', function () {
|
||||
$('#inputFile').val('');
|
||||
$('#file-chosen').text('未选择文件');
|
||||
});
|
||||
|
||||
// 当选择文件变化时,更新文件名显示
|
||||
$('#inputFile').on('change', function () {
|
||||
var fileName = $(this).val().split('\\').pop();
|
||||
$('#file-chosen').text(fileName || '未选择文件');
|
||||
});
|
||||
|
||||
// 处理上传按钮的点击事件
|
||||
$('#uploadBtn').on('click', function () {
|
||||
var inputFile = $('#inputFile').get(0).files[0];
|
||||
if (!inputFile) {
|
||||
showAlert('danger', '未选择文件');
|
||||
$('#uploadModal').modal('show');
|
||||
return;
|
||||
}
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('file', inputFile); // 将文件添加到 FormData 中
|
||||
formData.append('template_name', templateName);
|
||||
|
||||
$.ajax({
|
||||
url: '{{ excel_upload_config.parse_url }}',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
headers: {'X-CSRFToken': csrftoken},
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function (response) {
|
||||
window.location.href = response.redirect_url;
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
var errorMsg = "解析Excel文件失败。";
|
||||
if (xhr.responseJSON && xhr.responseJSON.error) {
|
||||
errorMsg = xhr.responseJSON.error;
|
||||
}
|
||||
showAlert('danger', errorMsg);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue