如何通过xlwings+Python结合Django接收Webhook更新LibreOffice .xlsx文件
问题排查与解决方案
核心问题分析
你的代码存在几个关键问题,导致Webhook触发后Excel无更新:
1. 代码结构错误:嵌套函数未被调用
orders函数定义在tradingview_webhook内部,且tradingview_webhook从未调用该函数,更新Excel的逻辑根本不会执行。此外,tradingview_webhook未添加@csrf_exempt和POST请求限制,Django会拦截Webhook的POST请求。
2. 语法错误:多余逗号导致变量类型异常
代码中多处末尾的逗号(如sht1 = wb.sheets["Sheet1"],、sht1.range('A1').value= "YES",)会让变量变成元组而非预期的工作表/值,调用range方法时会直接报错。
3. xlwings在Linux下的适配缺失
xlwings在Linux上需要主动连接LibreOffice服务,默认不会自动关联已打开的LibreOffice实例,且需要安装对应依赖。
4. Django视图返回值错误
视图函数直接返回字典而非JsonResponse/HttpResponse,Django会抛出500错误,Webhook无法收到正确响应。
分步解决方案
1. 安装xlwings LibreOffice依赖
pip install xlwings[libreoffice]
2. 启动LibreOffice服务模式
让LibreOffice在后台运行,允许xlwings连接操作:
libreoffice --headless --accept="socket,host=localhost,port=2002;urp;" --nofirststartwizard &
3. 修正后的完整代码
from django.shortcuts import render from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods import json, config, logbot, os import xlwings as xw # 配置xlwings连接LibreOffice服务 xw.Book.set_mock_caller(False) os.environ['XWINGS_CONNECTION'] = 'socket,host=localhost,port=2002;urp;' @csrf_exempt def home(request): return JsonResponse({'name': 'Hello'}) @csrf_exempt @require_http_methods(["POST"]) def tradingview_webhook(request): logbot.logs("========= STRATEGY =========") # 解析Webhook JSON数据 try: data = json.loads(request.body) except json.JSONDecodeError: logbot.logs(">>> /!\ Invalid JSON data", True) return JsonResponse({"success": False, "message": "invalid json data"}, status=400) # 验证密码 webhook_passphrase = os.environ.get('WEBHOOK_PASSPHRASE', config.WEBHOOK_PASSPHRASE) if 'passphrase' not in data or data['passphrase'] != webhook_passphrase: logbot.logs(">>> /!\ Invalid or missing passphrase", True) return JsonResponse({"success": False, "message": "invalid or missing passphrase"}, status=403) # 更新Excel逻辑 try: # 连接到LibreOffice中的工作簿(若已打开则复用实例,否则新建) wb = xw.Book('/home/tester.xlsx') sht1 = wb.sheets["Sheet1"] msg = data.get('message', '') if msg == 'entry': logbot.logs(">>> Order message : 'entry'") sht1.range('A1').value = "YES" sht1.range('A5').value = "NO" elif msg == 'exit': logbot.logs(">>> Order message : 'exit'") sht1.range('A1').value = "NO" sht1.range('A5').value = "YES" elif msg[-9:] == 'reverse': logbot.logs(">>> Order message : 'reverse'") sht1.range('A1').value = "NO" sht1.range('A5').value = "NO" else: logbot.logs(f">>> Order message : '{msg}'") return JsonResponse({"success": True, "message": f"unhandled message: {msg}"}) # 保存并刷新LibreOffice显示 wb.save() wb.app.refresh() return JsonResponse({"success": True, "message": msg}) except Exception as e: logbot.logs(f">>> /!\ Error updating Excel: {str(e)}", True) return JsonResponse({"success": False, "message": f"error updating excel: {str(e)}"}, status=500)
额外排查点
- 文件权限:确保运行Django的用户(如
www-data或你的个人用户)对/home/tester.xlsx有读写权限,可执行chmod 664 /home/tester.xlsx调整。 - LibreOffice实例冲突:若手动打开了
tester.xlsx,请关闭后测试,避免文件锁定导致无法写入。 - 日志检查:查看
logbot生成的日志,确认是否有具体报错(如找不到工作表、连接失败等)。 - xlwings版本:更新到最新版xlwings,旧版本对Linux的LibreOffice支持不完善。
内容的提问来源于stack exchange,提问作者Playr onezeroone
相关产品推荐
相关产品推荐

