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
相关产品推荐
相关产品推荐

