You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django实现CSV异步处理与结果邮件推送需求问询

Fixing Timeout Issues with Asynchronous Processing

Got it, let's fix that frustrating timeout problem by moving all the slow work to background tasks! Here's how you can refactor your code to give users an immediate confirmation while their request processes behind the scenes.

Step 1: Set Up Celery (Async Task Queue)

First, we'll use Celery—Django's go-to tool for async tasks. Install it along with Redis (our task broker):

pip install celery redis

Configure Celery in Your Project

  1. Create a celery.py file in your project root:
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project_name.settings')

app = Celery('your_project_name')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
  1. Add these settings to your settings.py:
CELERY_BROKER_URL = 'redis://localhost:6379/0'  # Use your Redis server URL
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
  1. Start the Celery worker (keep this running in a separate terminal):
celery -A your_project_name worker --loglevel=info

Step 2: Move Heavy Logic to an Async Task

Create a tasks.py file in your app directory, and transfer all the slow operations (CSV parsing, DB queries, email sending) into a Celery task:

from celery import shared_task
from django.core.mail import EmailMessage
import csv
from io import StringIO
import os
import logging
from .models import nummodel
from django.conf import settings

logger = logging.getLogger(__name__)

@shared_task
def process_bulk_search(temp_file_path, recipient_email):
    try:
        # Parse the uploaded CSV file
        with open(temp_file_path, 'r', encoding='utf-8') as csvfile:
            spamreader = csv.reader(csvfile, dialect='excel')
            next(spamreader)  # Skip header row
            number_list = [row[0].upper() for row in spamreader]

        # Fetch matching data from database
        data_list = nummodel.objects.filter(number__in=number_list)

        # Generate the output CSV
        output_csv = StringIO()
        writer = csv.writer(output_csv)
        writer.writerow(['a', 'b'])
        for data in data_list:
            writer.writerow([data.a, data.b])

        # Send the final report via email
        message = EmailMessage(
            "Your Bulk Search Report",
            "Your request has been processed! Find your report attached below.",
            "email@gmail.com",
            [recipient_email]
        )
        message.attach('invoice.csv', output_csv.getvalue(), 'text/csv')
        message.send()

        logger.info(f"Successfully sent report to {recipient_email}")
    
    except Exception as e:
        logger.error(f"Error processing bulk search: {str(e)}")
        # Optional: Notify user if something goes wrong
        error_msg = EmailMessage(
            "Bulk Search Failed",
            f"Sorry, we hit an issue processing your request: {str(e)}",
            "email@gmail.com",
            [recipient_email]
        )
        error_msg.send()
    
    finally:
        # Clean up the temporary file
        if os.path.exists(temp_file_path):
            os.remove(temp_file_path)

Step 3: Update Your View to Return Immediate Feedback

Modify your view to save the uploaded file temporarily, trigger the async task, and send the user a confirmation right away:

from django.shortcuts import render
from django.contrib import messages
import os
from django.conf import settings
from .tasks import process_bulk_search

def bulkserachpro(request):
    if request.method == 'POST' and request.FILES.get('searchnum'):
        uploaded_file = request.FILES['searchnum']
        
        # Create a temp directory to store the uploaded file
        temp_dir = os.path.join(settings.MEDIA_ROOT, 'temp_bulk_searches')
        os.makedirs(temp_dir, exist_ok=True)
        temp_file_path = os.path.join(temp_dir, uploaded_file.name)

        # Save the uploaded file to temp location
        with open(temp_file_path, 'wb+') as destination:
            for chunk in uploaded_file.chunks():
                destination.write(chunk)
        
        # Get recipient email (adjust this to use the user's actual email, e.g., from request.user)
        recipient_email = request.user.email if request.user.is_authenticated else "emailto@gmail.com"
        
        # Trigger the async task
        process_bulk_search.delay(temp_file_path, recipient_email)

        # Send immediate success message to the user
        messages.success(request, '文件已接收,我们会尽快处理并将报告发送至您的邮箱,请留意查收!')
        return render(request, 'bulkpro.html')
    
    return render(request, 'bulkpro.html')

Key Tips

  • Keep Celery Running: The Celery worker must stay active for tasks to execute—don't close its terminal window.
  • Handle Large Files: Saving the file temporarily instead of passing its content directly avoids memory overload with big CSVs.
  • Personalize Emails: Replace the hardcoded recipient email with the user's actual email (e.g., from a form field or their account profile) for a better experience.
  • Monitor Errors: The task includes logging to help you debug any issues that pop up during processing.

内容的提问来源于stack exchange,提问作者Sapna Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:27:31