docassemble 1.10.15 排错FAQ

docassemble 1.10.15 排错 FAQ 合集:登录路径与密码策略、首启慢与安全关机数据回档、访谈 YAML 高频坑(mandatory/插值/current_datetime/person.name.first/event 块/错误态缓存/Exit 按钮取值)、Web 端点路径纠错、脚本化对接与备份权限,23 问全部来自实测踩坑记录。

docassembledocassembleDockerDocker ComposePython 编程2026/11/01

docassemble 1.10.15 排错FAQ

目标:把 docassemble 1.10.15 单容器全栈部署上「真实踩过并解决」的坑整理成即查即用的问答。本文每一条现象、报错原文与处置命令均来自实测环境(Ubuntu 26.04.1 LTS 宿主,compose 项目 docassemble-1.10.15-stack,容器 docassemble-1.10.15-web,端口 8139→80,docassemble 1.10.15),未实测的推断一律不收录。部署与运维主线见 《docassemble 1.10.15 Docker Compose 部署指南》 与 《docassemble 1.10.15 日常运维与升级指南》。

一、环境信息

  • 应用:docassemble 1.10.15(jhpyle/docassemble 官方全栈镜像,supervisord 管理 Web/uwsgi/nginx/PostgreSQL 18.6/Redis 8.0.5/RabbitMQ 4.0.5/Celery 5.6.3)
  • Python:3.14.4,虚拟环境 /usr/share/docassemble/local3.14;Flask 3.1.3
  • 主配置:/usr/share/docassemble/config/config.yml(实测关键值:enable playground: true、allow log viewing: true、enable api: True、exitpage: https://docassemble.org)
  • 数据库:PGPASSWORD=abc123 psql -U docassemble -d docassemble -h localhost(实测 public 模式 25 张表)
  • 应用日志:/usr/share/docassemble/log/docassemble.log(排障第一现场)
  • 演示账号:admin@example.com / Q1w2e3r4(出厂为 password,首登强制改密;q1w2e3r4 会被密码策略拒绝,见 Q3)

二、登录与账号

Q1: 访问登录页 404? A: 本版本登录路径是 /user/sign-in(实测 GET 200)。/users/signin 是旧版 Rails 风格路径写法,实测 404。管理员后台各页路径以 /interviews、/config、/logs、/monitor 为准(见 Q17、Q18)。

Q2: 出厂账号登录后被强制跳转,进不去后台? A: 正常行为。实测 admin@example.com / password 首登成功后系统 302 到 /user/change-password?next=/interviews,必须改密。改密成功回显:200 http://localhost/interviews?from_login=1,页面 <title>Interviews</title>。

Q3: 改密时提示密码不合规? A: 密码策略实测报错原文:

Password must be at least six characters long with at least one
lowercase letter, at least one uppercase letter...

常见弱口令形态 q1w2e3r4 因缺大写字母被拒;按策略补大写(如 Q1w2e3r4)实测通过。

三、部署与启动

Q4: 部署后访问 http://localhost:8139 一直显示 "Docassemble is starting"? A: 首启正常现象,不是故障。initialize 要跑 apt-get update、pip 依赖与 NLTK 词库下载,实测总时长约 17 分钟。观察进度:

docker logs -f docassemble-1.10.15-web 2>&1 | grep -E 'success: .* entered RUNNING'

实测时序样例(节选):

2026-11-01 07:44:05,182 INFO success: rabbitmq entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2026-11-01 07:44:10,923 INFO success: celery entered RUNNING state, process has stayed up for > than 5 seconds (startsecs)

就绪判据:curl -s http://localhost:8139/ | grep -oE '<title>[^<]+</title>' 从 <title>Docassemble is starting</title> 变为 <title>Default interview</title>。

Q5: 重启后配置/访谈文件回档到旧版本,或开机日志出现 initialize: unsafe shutdown detected; will not restore from backup? A: 上次停机被强杀(docker kill、docker stop -t 1 或宿主机断电),遗留 da_running 标记触发了保护逻辑(实测 initialize.sh 段):

RESTOREFROMBACKUP=true
if [ -f /var/run/docassemble/da_running ] || [ -f /var/run/docassemble/status-rabbitmq-running ]; then
    echo "initialize: unsafe shutdown detected; will not restore from backup" >&2
    RESTOREFROMBACKUP=false
fi

此时盘上是「强杀前的残局」,系统故意不用 backup 覆盖。处置:若确认要以备份为准,手动把 backup 卷内 config.yml、files/、postgres/ 拷回原位再 supervisorctl start reset;预防则是 compose 里 stop_grace_period: 600s(官方 docker stop -t 600 口径),停机一律 docker compose down。

Q6: 手动 pg_dump 到备份目录报 Permission denied? A: 实测报错原文:

pg_dump: error: could not open output file "/usr/share/docassemble/backup/manual-test.pgd": Permission denied

backup 目录属 root,postgres 用户不可直接写。官方 cron 的写法是先落 postgres 属主临时目录、再由 root rsync:

docker exec docassemble-1.10.15-web bash -lc \
  'D=$(mktemp -d); chown postgres:postgres $D; \
   su postgres -c "cd /tmp; pg_dump -F c -f $D/docassemble docassemble"; \
   ls -la $D'
-rw-rw-r-- 1 postgres postgres 98187 Nov  1 22:34 docassemble

Q7: docker pull jhpyle/docassemble 或查 Docker Hub tag 超时? A: 本环境实测 hub.docker.com 直连超时(curl 无回显),改走代理 192.168.1.72:7897 后 HTTP 200 成功。镜像拉取本身走宿主 Docker 守护进程既有加速器/代理配置即可;GitHub API 同理。文档站 docassemble.org 实测可直连。

四、访谈创建与运行(YAML 高频坑)

Q8: 访谈打开报 501:Docassemble has finished executing all code blocks marked as initial or mandatory, and finished asking all questions marked as mandatory (if any). It is a best practice to end your interview with a question that says goodbye.? A: 新手第一坑,实测踩中。docassemble 是拉取模型:引擎只执行标了 initial/mandatory 的代码块,并倒推回答未定义变量所需的问题。question 块既没 mandatory: True、也没有其他块引用它产生的变量,引擎就认为「无事可做」直接抛此错。处置:给入口问题加 mandatory: True。实测修复后同一访谈正常出题(见 Q14 运行序列)。

Q9: 页面把 { person.name.first } 原样显示,不替换成值? A: 插值必须用 ${ }(dollar-brace),单花括号不渲染,实测原样输出。正确写法:您好,${ person.name.first }!。

Q10: 用 today_datetime() 报错? A: 实测报错原文:

reference to a variable 'today_datetime' that could not be looked up in the question file (for language 'en') or in any of the files incorporated by reference into the question file

1.10.15 已移除 today_datetime(),取当前时间用 current_datetime();且所有引擎函数需要显式导入,YAML 顶部加:

---
modules:
  - docassemble.base.util

不加 modules 导入时 current_datetime() 同样报 could not be looked up(实测)。

Q11: 定义了 objects: - person: Individual,写 { person.name }/${ person.name } 仍报错? A: 实测报错原文:

reference to a variable 'person.name.first' that could not be looked up in the question file (for language 'en') or in any of the files incorporated by reference into the question file

Individual 对象的姓名是复合属性,提问/引用都要落到 person.name.first 层级(引擎倒推时也会把 person.name 展开成 person.name.first 去查找)。fields 写法实测通过形态:- 姓名: person.name.first。

Q12: event: 块配 content: 报 No question type could be determined for this section.? A: 实测踩中。1.10.15 中 event 块若没有可判定的问题类型(无 question/buttons/fields 等)即报此句。退出类 event 页的实测可用写法是「question + buttons」形态:

---
id: greeting
question: 您好,${ person.name.first }!这是 docassemble 实测访谈。
subquestion: |
  当前服务器时间:${ current_datetime() }
buttons:
  - Exit: exit
mandatory: True

Q13: 修好了 YAML,重新打开访谈仍然显示旧错误页? A: 错误状态按「用户+访谈 URL」持久化缓存在 PG userdict 表(实测:filename=访谈 URL、key=session 的行存有错误态),改文件不会自动清。实测处置:

docker exec docassemble-1.10.15-web bash -lc \
  'echo "DELETE FROM userdict WHERE filename LIKE '"'"'%g25final%'"'"';" | PGPASSWORD=abc123 psql -U docassemble -d docassemble -h localhost'
# DELETE 1

删除后刷新访谈即干净重跑。注意 interviews 表不存在(实测),别去那张表找——访谈定义在 files/playground/ 磁盘文件里,库里只有会话与审计状态。

Q14: 脚本化跑访谈时,点 Exit 按钮报 int('exit') ValueError? A: 实测日志原文(docassemble.log):

docassemble: ip=10.89.61.1 i=docassemble.playground1:g25final.yml uid=idJ6ZcaFkHNnHosBLP38lCWw2MXjAQ4D user=admin@example.com 2026-11-01 22:20:47 Tried to run _internal["answers"]['ID greeting'] = int('exit') and got error ValueError: invalid literal for int() with base 10: 'exit'

原因:buttons 提交时表单字段 _multiple_choice 的 value 是按钮索引(实测 "0"),不是动作字符串 exit。POST 时把 exit 改成 "0" 后实测走通:POST /interview?i=docassemble.playground1:g25final.yml → 302,Location: https://docassemble.org(config.yml exitpage 生效)。

Q15: 自动化提交答案时,POST 了但答案没保存、页面退回上一题? A: 实测踩中:请求参数里带了 _back_one=1,docassemble 把它当作「返回上一题」导航操作,跳过答案存储。脚本化提交时剔除该参数即正常。

Q16: 脚本 POST 表单返回 400:flask_wtf.csrf.CSRFError: 400 Bad Request: The CSRF token is missing.? A: 实测日志原文即此句。docassemble 所有 Web 表单(登录、playground 保存、访谈提交)都带 csrf_token 字段,脚本必须先 GET 同一页面取 token 与 Cookie,再随 POST 提交;直接裸 POST 必 400。登录流程实测形态:GET /user/sign-in 取 csrf_token → POST email/password/csrf_token → 302 即登录成功。

五、Web 端点与运维集成

Q17: 日志页/监控页 404? A: 路径实测:/logs 200(<title>Logs</title>,受 allow log viewing: true 控制);/log 404。监控页是 /monitor 200(<title>Monitor</title>);/manage 实测 404。管理员侧栏入口以登录页实测链接为准:/config、/interviews、/playground、/user/sign-in。

Q18: 想脚本化新建 Playground 访谈,/playground/create-new 404? A: 实测该路径不存在。Playground 页面(/playground?project=default,实测 <title>Playground</title>)的全部操作都 POST 回同一端点,表单字段实测为:playground_name(文件名)、playground_content(内容)、status、csrf_token、submit(按钮值,如 Save)。新建/保存成功后响应页仍是 <title>Playground</title>,文件落盘位置实测 /usr/share/docassemble/files/playground/1/<名字>.yml。

Q19: 容器里找不到 docassemble 命令行工具? A: 设计如此,不是安装缺损。实测 docassemble --help 返回 executable file not found in $PATH(exit 127),venv bin/ 与 webapp 包均无 CLI 入口。管理面就是四件套:supervisorctl(进程)、psql(数据)、redis-cli(缓存)、Web 后台(/config、/logs、/monitor、/playgroundpackages?project=default)。

Q20: 听说 docassemble 全文检索要配 Elasticsearch,容器里找不到? A: 实测本镜像不含 Elasticsearch:supervisorctl 全单元清单(20 项)与进程列表均无 ES 相关条目。docassemble 的搜索走 PostgreSQL 自身,无需额外部署 ES。

Q21: 调 API 返回 404? A: 实测 GET http://localhost:8139/api(不带密钥)直接返回 404 HTML 页而非 401/403 JSON——容易误判为「API 没开」。config.yml 实测 enable api: True 时 API 已启用,正确调用必须带 api_key 参数(密钥签发方式见官方 API 文档,本文「六、参考链接」),如 GET /api/interview?i=docassemble.playground1:g25final.yml&api_key=<密钥>。另外注意访谈页本身匿名可开(实测未登录 GET /interview?i=docassemble.playground1:g25final.yml 返回 200),这与 API 鉴权是两套体系。

Q22: curl 上传 YAML 到 playground,存进去的内容是字面量 @g25final.yml? A: --data-urlencode 的文件展开语法是 field@file(没有等号)。写成 --data-urlencode 'playground_content=@g25final.yml' 会把 @g25final.yml 当字面量提交(实测踩中,playground 里存进的就是这串字符)。正确示例(端点与字段名实测见 Q18):

curl -s -b jar.txt \
     --data-urlencode 'playground_content@g25final.yml' \
     --data-urlencode 'playground_name=g25final.yml' \
     --data-urlencode 'csrf_token=<TOKEN>' \
     --data-urlencode 'submit=Save' \
     'http://localhost:8139/playground?project=default'

Q23: 改了 config.yml 或装了扩展包,行为没变化? A: 配置与包变更需要重载应用进程才生效。实测两种生效动作:轻量改动 supervisorctl restart uwsgi;涉及包/引擎行为 supervisorctl start reset(一次性程序,并行重启 uwsgi/websockets/celery/rabbitmq,实测回显 reset: started,随后 celery STARTING→RUNNING,uwsgi/nginx 进程号不变)。环境变量类(DAHOSTNAME 等)只在开机生成 config.yml 时生效,改它们要 docker compose up -d 重建容器。

六、参考链接

docassemble 1.10.15 排错FAQ - Quzuo