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

React与Django交互:CSV文件上传、处理及结果返回方案咨询

React + Django 实现CSV无存储式处理方案

前端React实现(文件上传与结果展示)

用FormData直接传输CSV文件,无需提前序列化,适配Django的文件接收逻辑:

import { useState } from 'react';

function CSVUploader() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [results, setResults] = useState(null);
  const [errorMsg, setErrorMsg] = useState('');

  const handleFilePick = (e) => {
    const file = e.target.files[0];
    if (file && file.type === 'text/csv') {
      setSelectedFile(file);
      setErrorMsg('');
      setResults(null);
    } else {
      setErrorMsg('请选择有效的CSV文件');
    }
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!selectedFile) return;

    const formData = new FormData();
    formData.append('csv_file', selectedFile);

    try {
      const res = await fetch('/api/process-csv/', {
        method: 'POST',
        headers: {
          'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
        },
        body: formData,
      });

      if (!res.ok) throw new Error('服务器处理失败');
      const data = await res.json();
      setResults(data);
    } catch (err) {
      setErrorMsg(err.message);
    }
  };

  return (
    <div className="upload-container">
      <form onSubmit={handleSubmit}>
        <input type="file" accept=".csv" onChange={handleFilePick} />
        <button type="submit" disabled={!selectedFile}>上传处理</button>
      </form>
      
      {errorMsg && <p className="error">{errorMsg}</p>}
      
      {results && (
        <div className="results">
          <h3>处理结果</h3>
          <div className="model-info">
            <p>模型系数:{results.model_coef.join(', ')}</p>
            <p>截距:{results.model_intercept}</p>
          </div>
          <img src={`data:image/png;base64,${results.chart_base64}`} alt="预测趋势图" />
          <a href={`/api/generate-pdf/?task_id=${results.task_id}`} target="_blank" rel="noopener noreferrer">
            下载PDF报告
          </a>
        </div>
      )}
    </div>
  );
}

export default CSVUploader;

后端Django实现(文件接收与内存处理)

不存储文件到数据库,直接在内存中解析CSV,处理完成后返回结果:

1. 视图逻辑

from django.views import View
from django.http import JsonResponse, HttpResponse
from django.conf import settings
import pandas as pd
import io
import base64
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
import uuid
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

class CSVProcessView(View):
    def post(self, request):
        # 校验文件是否存在
        if 'csv_file' not in request.FILES:
            return JsonResponse({'error': '未上传CSV文件'}, status=400)
        
        csv_file = request.FILES['csv_file']
        # 内存中读取CSV,避免写入数据库
        try:
            df = pd.read_csv(io.StringIO(csv_file.read().decode('utf-8')))
        except Exception as e:
            return JsonResponse({'error': f'CSV解析失败: {str(e)}'}, status=400)
        
        # 替换为你的数据挖掘算法(示例用线性回归)
        required_cols = ['feature', 'target']
        if not all(col in df.columns for col in required_cols):
            return JsonResponse({'error': 'CSV缺少特征/目标列'}, status=400)
        
        X = df[['feature']]
        y = df['target']
        model = LinearRegression()
        model.fit(X, y)
        predictions = model.predict(X).tolist()
        
        # 生成图表并转base64返回前端
        plt.figure(figsize=(8, 5))
        plt.scatter(df['feature'], df['target'], label='原始数据')
        plt.plot(df['feature'], predictions, color='red', label='预测曲线')
        plt.legend()
        buffer = io.BytesIO()
        plt.savefig(buffer, format='png', bbox_inches='tight')
        buffer.seek(0)
        chart_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
        plt.close()
        
        # 生成临时任务ID,用于关联后续PDF生成的临时数据
        task_id = str(uuid.uuid4())
        temp_dir = os.path.join(settings.BASE_DIR, 'temp_csv_data')
        os.makedirs(temp_dir, exist_ok=True)
        # 临时保存处理后的数据(生成PDF时用)
        df['predictions'] = predictions
        df.to_csv(os.path.join(temp_dir, f'{task_id}.csv'), index=False)
        
        return JsonResponse({
            'predictions': predictions,
            'model_coef': model.coef_.tolist(),
            'model_intercept': float(model.intercept_),
            'chart_base64': chart_base64,
            'task_id': task_id
        })

class PDFGenerateView(View):
    def get(self, request):
        task_id = request.GET.get('task_id')
        if not task_id:
            return JsonResponse({'error': '缺少任务ID'}, status=400)
        
        temp_file_path = os.path.join(settings.BASE_DIR, 'temp_csv_data', f'{task_id}.csv')
        if not os.path.exists(temp_file_path):
            return JsonResponse({'error': '数据已过期'}, status=404)
        
        df = pd.read_csv(temp_file_path)
        # 生成PDF内容
        buffer = io.BytesIO()
        p = canvas.Canvas(buffer, pagesize=letter)
        width, height = letter
        
        # 写入标题与模型信息
        p.setFont("Helvetica-Bold", 16)
        p.drawString(100, height-50, '数据挖掘分析报告')
        p.setFont("Helvetica", 12)
        p.drawString(100, height-80, f'模型系数: {df["predictions"].iloc[0]:.2f}')
        p.drawString(100, height-100, f'截距: {df["predictions"].iloc[0]:.2f}')
        
        # 写入数据表格(简化版,可使用ReportLab的Table组件优化)
        y_pos = height - 130
        p.drawString(100, y_pos, '特征值 | 实际值 | 预测值')
        y_pos -= 20
        for _, row in df.iterrows():
            p.drawString(100, y_pos, f'{row["feature"]:.2f} | {row["target"]:.2f} | {row["predictions"]:.2f}')
            y_pos -= 20
            if y_pos < 50:
                p.showPage()
                y_pos = height - 50
        
        p.save()
        buffer.seek(0)
        
        # 返回PDF文件
        response = HttpResponse(buffer, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="report_{task_id}.pdf"'
        
        # 清理临时文件
        os.remove(temp_file_path)
        return response

2. URL配置

from django.urls import path
from .views import CSVProcessView, PDFGenerateView

urlpatterns = [
    path('api/process-csv/', CSVProcessView.as_view(), name='process_csv'),
    path('api/generate-pdf/', PDFGenerateView.as_view(), name='generate_pdf'),
]

关键注意事项

  • 依赖安装:执行pip install pandas matplotlib scikit-learn reportlab安装所需库
  • 临时文件清理:可添加定时任务(如Celery)定期删除temp_csv_data目录下的过期文件
  • 文件大小限制:在Django的settings.py中设置FILE_UPLOAD_MAX_MEMORY_SIZE控制可上传的最大文件大小
  • 前后端分离场景:若React部署在独立域名,需在Django的settings.py中配置CSRF_TRUSTED_ORIGINS并让前端携带正确的CSRF Token

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:15:38