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

无REST API时Django转React前端及数据传递方法咨询

从Django模板迁移到React静态HTML的解决方案

结合你的场景(无独立服务器、最终输出静态HTML发邮件),核心思路是让Django负责数据处理,React负责UI渲染,最终生成纯静态的HTML文件。下面是具体的步骤和实现细节:

1. 数据传递:让Django把数据交给React

因为无法调用接口,所以需要在静态生成阶段把Django处理好的数据直接传递给React,有两种常用方式:

方式一:Django生成JSON数据文件

在Django中处理完数据后,将其序列化为JSON文件保存到指定目录,比如data/report_data.json:

# Django视图/脚本示例
import json
from django.conf import settings
import os

def export_report_data():
    # 处理数据生成tables、图表数据等
    processed_data = {
        "tables": {
            "sales": [{"month": "Jan", "amount": 1200}, {"month": "Feb", "amount": 1800}],
            "active_users": [{"region": "North", "count": 500}, {"region": "South", "count": 300}]
        },
        "chart_data": {"monthly_revenue": [1200, 1800, 1500, 2200]}
    }
    # 保存为JSON文件
    output_path = os.path.join(settings.BASE_DIR, "data", "report_data.json")
    with open(output_path, "w") as f:
        json.dump(processed_data, f, indent=2)

方式二:Django直接将数据嵌入HTML模板

如果不需要单独的JSON文件,可以在Django模板中通过全局变量传递数据:

<!-- Django基础模板 -->
<script>
  window.REPORT_DATA = {{ serialized_data|safe }};
</script>

其中serialized_data是Django视图中用json.dumps()处理后的字符串,加上|safe标签避免转义。

2. 模板转换:把Django模板语法转成React JSX

将你原有的Django模板逻辑,替换成React的组件式写法:

原Django模板片段

<div class="card">
  {% for k, v in tables.items %}
    <div id="{{ k }}">
      <h3>{{ k|title }}</h3>
      <table>
        {% for row in v %}
          <tr>
            {% for val in row.values %}
              <td>{{ val }}</td>
            {% endfor %}
          </tr>
        {% endfor %}
      </table>
    </div>
  {% endfor %}
</div>

对应的React组件

import React from 'react';

// 接收Django传递的数据作为props
function ReportCard({ tables }) {
  return (
    <div className="card">
      {/* 替换Django的{% for %}循环为Object.entries().map() */}
      {Object.entries(tables).map(([tableKey, tableRows]) => (
        <div key={tableKey} id={tableKey}>
          {/* 替换Django的{{ k|title }}为JS字符串处理 */}
          <h3>{tableKey.charAt(0).toUpperCase() + tableKey.slice(1)}</h3>
          <table>
            <tbody>
              {tableRows.map((row, rowIndex) => (
                <tr key={rowIndex}>
                  {Object.values(row).map((cellVal, cellIndex) => (
                    <td key={cellIndex}>{cellVal}</td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      ))}
    </div>
  );
}

export default ReportCard;

图表处理

如果原来Django用后端工具生成图表图片,现在可以用React的静态图表库(比如Recharts)直接基于数据渲染SVG图表,这样生成的HTML自带矢量图,邮件兼容性更好:

import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

function RevenueChart({ data }) {
  // 格式化Django传递的图表数据为Recharts需要的结构
  const chartData = data.map((value, index) => ({
    month: ['Jan', 'Feb', 'Mar', 'Apr'][index],
    revenue: value
  }));

  return (
    <div className="chart-container">
      <h3>Monthly Revenue Trend</h3>
      <ResponsiveContainer width="100%" height={300}>
        <LineChart data={chartData}>
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="month" />
          <YAxis />
          <Tooltip />
          <Line type="monotone" dataKey="revenue" stroke="#2196F3" strokeWidth={2} />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}

3. 生成静态HTML:让React输出纯静态内容

因为邮件客户端大多禁用JavaScript,所以必须生成预渲染的纯静态HTML,不能依赖客户端React渲染。有两种实现方式:

方式一:用ReactDOMServer做服务器端渲染(SSR)

写一个Node.js脚本,读取Django生成的数据,用ReactDOMServer.renderToString()把组件渲染成HTML字符串:

const React = require('react');
const ReactDOMServer = require('react-dom/server');
const fs = require('fs');
const path = require('path');
const ReportCard = require('./src/components/ReportCard').default;
const RevenueChart = require('./src/components/RevenueChart').default;

// 读取Django生成的JSON数据
const dataPath = path.join(__dirname, 'data', 'report_data.json');
const reportData = JSON.parse(fs.readFileSync(dataPath, 'utf8'));

// 渲染组件为HTML字符串
const renderedHTML = ReactDOMServer.renderToString(
  <div>
    <h1>Monthly Business Report</h1>
    <ReportCard tables={reportData.tables} />
    <RevenueChart data={reportData.chart_data.monthly_revenue} />
  </div>
);

// 把渲染后的HTML插入到基础模板中
const baseTemplate = fs.readFileSync(path.join(__dirname, 'templates', 'base.html'), 'utf8');
const finalHTML = baseTemplate.replace('{{ react_content }}', renderedHTML);

// 保存最终静态HTML
fs.writeFileSync(path.join(__dirname, 'output', 'report.html'), finalHTML);

方式二:用Next.js静态导出

如果你的React应用较复杂,可以用Next.js的静态生成能力:

  1. 在Next.js页面中读取Django生成的JSON数据:
// pages/report.js
import fs from 'fs/promises';
import path from 'path';
import ReportCard from '../components/ReportCard';
import RevenueChart from '../components/RevenueChart';

export async function getStaticProps() {
  const dataPath = path.join(process.cwd(), 'data', 'report_data.json');
  const jsonData = await fs.readFile(dataPath, 'utf8');
  const reportData = JSON.parse(jsonData);
  return { props: reportData };
}

export default function ReportPage({ tables, chart_data }) {
  return (
    <div>
      <h1>Monthly Business Report</h1>
      <ReportCard tables={tables} />
      <RevenueChart data={chart_data.monthly_revenue} />
    </div>
  );
}
  1. 运行next build && next export,Next.js会自动生成纯静态的HTML文件到out目录。

4. 整合到django-bakery流程

把React静态生成的步骤加入到django-bakery的构建流程中:

  1. 在Django的构建脚本中,先调用数据导出函数生成JSON文件。
  2. 执行Node.js脚本或Next.js导出命令生成静态HTML。
  3. 把生成的HTML文件复制到django-bakery的输出目录,最终一起打包或发送邮件。

关键注意事项

  • 邮件兼容性:尽量使用简单的HTML结构,优先用内联样式(避免外部CSS文件或<style>标签),因为多数邮件客户端对复杂CSS支持有限。
  • 依赖环境:需要在Django运行环境中安装Node.js和React相关依赖(比如react、react-dom、recharts等)。
  • 数据序列化:确保Django生成的JSON数据格式正确,处理好日期、特殊字符等,可通过json.dumps(data, ensure_ascii=False)支持中文。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:59:56