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

Django站点需求:双击表格行生成含选中data的可下载PyInstaller编译文件

实现Django站点中双击表格行生成并下载编译后的Python客户端程序

一、前端修改:双击行后提交选中的data到后端

将原JS逻辑改为发送POST请求到Django后端,同时处理CSRF验证:

const table = document.getElementById('table');
const rows = table.getElementsByTagName('tr');

Array.from(rows).forEach((row, index) => {
  row.addEventListener('dblclick', () => {
    const cells = row.getElementsByTagName('td');
    const selectedData = cells[1].innerHTML; // 假设data列是表格第二列(索引1)
    // 发送请求到后端生成客户端程序
    fetch('/generate-client/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRFToken': getCookie('csrftoken')
      },
      body: JSON.stringify({ data: selectedData })
    })
    .then(response => {
      if (!response.ok) throw new Error('请求失败');
      return response.blob();
    })
    .then(blob => {
      // 创建下载链接并触发下载
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'sender.exe'; // 根据服务器系统调整后缀:Mac用sender.zip,Linux用sender
      document.body.appendChild(a);
      a.click();
      // 清理资源
      window.URL.revokeObjectURL(url);
      document.body.removeChild(a);
    })
    .catch(err => console.error('生成客户端失败:', err));
  });
});

// 辅助函数:获取Django的CSRF令牌
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.startsWith(name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}

二、Django后端实现:生成代码、编译并返回下载文件

1. 添加URL路由

在项目urls.py中新增路由:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    # 其他已存在路由...
    path('generate-client/', views.generate_client, name='generate-client'),
]

2. 编写视图函数

在views.py中实现生成代码、编译、返回下载的逻辑:

# views.py
import os
import tempfile
import subprocess
from django.http import HttpResponse, JsonResponse

# sender.py模板,用{data}作为占位符替换选中内容
SENDER_TEMPLATE = """from somelib import func

constData = "{data}"

if constData is not None and len(constData) > 0:
    print("Argument constData is valid")
    constData = str(constData)
    client = func(constData, 9999)
    client.func2()
else:
    print("Argument constData is invalid")
"""

def generate_client(request):
    if request.method != 'POST':
        return JsonResponse({'error': '仅支持POST请求'}, status=405)
    
    try:
        # 获取前端传入的data
        request_data = request.json
        selected_data = request_data.get('data')
        if not selected_data:
            return JsonResponse({'error': '未传入有效data'}, status=400)
        
        # 创建临时目录存放文件
        with tempfile.TemporaryDirectory() as temp_dir:
            # 生成sender.py文件(转义引号避免语法错误)
            sender_file_path = os.path.join(temp_dir, 'sender.py')
            with open(sender_file_path, 'w', encoding='utf-8') as f:
                f.write(SENDER_TEMPLATE.format(data=selected_data.replace('"', '\\"')))
            
            # 调用PyInstaller编译成单文件
            subprocess.run(
                [
                    'pyinstaller',
                    '--onefile',
                    '--distpath', temp_dir,
                    '--workpath', os.path.join(temp_dir, 'build'),
                    '--specpath', temp_dir,
                    sender_file_path
                ],
                check=True,
                capture_output=True,
                text=True
            )
            
            # 根据操作系统确定编译后的文件名
            compiled_filename = 'sender'
            if os.name == 'nt':
                compiled_filename += '.exe'
            elif os.uname().sysname == 'Darwin':
                # Mac下.app是文件夹,打包成zip才能下载
                subprocess.run(['zip', '-r', 'sender.zip', 'sender.app'], cwd=temp_dir, check=True)
                compiled_filename = 'sender.zip'
            
            compiled_file_path = os.path.join(temp_dir, compiled_filename)
            
            # 返回下载文件
            with open(compiled_file_path, 'rb') as f:
                response = HttpResponse(f.read(), content_type='application/octet-stream')
                response['Content-Disposition'] = f'attachment; filename="{compiled_filename}"'
                return response
    
    except subprocess.CalledProcessError as e:
        return JsonResponse({'error': f'编译失败: {e.stderr}'}, status=500)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

三、关键注意事项

  • PyInstaller安装:确保Django环境已安装PyInstaller,执行pip install pyinstaller
  • 跨平台限制:PyInstaller只能在对应系统编译对应格式程序(Windows→exe,Mac→app,Linux→可执行文件),需根据部署环境调整
  • 依赖打包:如果somelib是自定义库,需在PyInstaller命令中添加--hidden-import somelib参数
  • 临时文件清理:tempfile.TemporaryDirectory会自动清理临时文件,避免磁盘占用
  • 权限设置:Django运行用户需具备创建临时目录、执行PyInstaller的权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:40:29