使用Django Celery进行Excel导入和导出

2023-04-11 00:00:00 django 导入 导出

首先,我们需要安装Django Celery和pandas库:

pip install django-celery
pip install pandas

接下来,在Django项目的settings.py文件中添加如下配置:

# 启用Celery
CELERY_IMPORTS = ('myapp.tasks',)
CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
BROKER_URL = 'redis://localhost:6379/0'

# pandas读取文件编码格式
PANDAS_READ_ENCODING = 'utf-8'

# 导出Excel时的行高和列宽
EXCEL_ROW_HEIGHT = 20
EXCEL_COLUMN_WIDTH = 15

然后,在Django项目的urls.py文件中添加如下配置:

from django.conf.urls import url, include
from django.contrib import admin

import myapp.views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^export-excel/$', myapp.views.export_excel),
    url(r'^import-excel/$', myapp.views.import_excel),
]

接着,我们需要在myapp中新建tasks.py文件,用于处理Excel导入和导出的任务:

from __future__ import absolute_import
from celery import shared_task
import pandas as pd
from django.core.files.uploadedfile import TemporaryUploadedFile
from django.conf import settings


@shared_task
def export_excel(filename, data):
    df = pd.DataFrame(data)
    writer = pd.ExcelWriter(filename)
    df.to_excel(writer, sheet_name='Sheet1', index=False)
    worksheet = writer.sheets['Sheet1']
    for i, col in enumerate(df.columns):
        column_len = df[col].astype(str).str.len().max()
        column_len = max(column_len, len(col))
        worksheet.set_column(i, i, settings.EXCEL_COLUMN_WIDTH)
        worksheet.set_column(i, i, column_len)
        worksheet.set_row(0, settings.EXCEL_ROW_HEIGHT)
    writer.save()


@shared_task
def import_excel(file):
    if isinstance(file, TemporaryUploadedFile):
        file_path = file.temporary_file_path()
    else:
        file_path = file
    df = pd.read_excel(file_path, encoding=settings.PANDAS_READ_ENCODING)
    return df.to_dict(orient='records')

在views.py文件中,我们将使用Celery异步执行任务,同时也处理Excel文件的上传和下载:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.core.files.storage import FileSystemStorage
from django.urls import reverse
from django.contrib import messages
from django.conf import settings

from myapp.tasks import export_excel, import_excel


def export_excel(request):
    if request.method == 'POST':
        data = [
            {'name': '张三', 'age': 18},
            {'name': '李四', 'age': 20},
            {'name': '王五', 'age': 16},
        ]
        filename = 'export.xlsx'
        export_excel.delay(filename, data)
        return redirect(reverse('myapp:export_excel'))
    else:
        return render(request, 'myapp/export_excel.html')


def import_excel(request):
    if request.method == 'POST':
        uploaded_file = request.FILES['file']
        fs = FileSystemStorage()
        filename = fs.save(uploaded_file.name, uploaded_file)
        file_url = fs.url(filename)
        result = import_excel.delay(file_url)
        result_str = '导入成功,共导入了%d条记录' % len(result.get())
        messages.success(request, result_str)
        return redirect(reverse('myapp:import_excel'))
    else:
        return render(request, 'myapp/import_excel.html')

最后,我们需要在templates目录中新建export_excel.html和import_excel.html模板文件,用于展示Excel导入和导出的页面:

export_excel.html:

{% extends "base.html" %}

{% block content %}
    <h1>导出Excel</h1>
    <form method="post">
        {% csrf_token %}
        <input type="submit" value="导出Excel">
    </form>
{% endblock %}

import_excel.html:

{% extends "base.html" %}

{% block content %}
    <h1>导入Excel</h1>
    {% if messages %}
        <ul class="messages">
            {% for message in messages %}
                <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
            {% endfor %}
        </ul>
    {% endif %}
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="file" name="file">
        <input type="submit" value="导入Excel">
    </form>
{% endblock %}

通过以上步骤,就可以使用Django Celery进行Excel导入和导出了。在任务较重的情况下,使用Celery异步执行任务可以大大提高网站的响应速度。

相关文章