使用Dynaconf的@get获取列表时出现意外的嵌套字典问题
看起来你遇到了Dynaconf使用@get引用嵌套标量值时的一个常见小陷阱,我来帮你拆解原因和解决办法。
问题原因分析
你观察到的现象核心在于:当用@get指向具体的叶子节点(比如列表、字符串这类标量值),并把它赋值给另一个嵌套结构下的同名键时,Dynaconf的解析逻辑会意外地把这个值包装成一个字典。比如你写:
[default.celery.google.calendar] calendar_ids = '@get google.calendar.calendar_ids'
Dynaconf会把calendar_ids的值解析为{"calendar_ids": ["a", "b"]},而不是直接将列表["a", "b"]赋值给calendar_ids。
而carrot.google = '@get google'能正常工作,是因为这里直接引用了整个google节点(一个字典结构),Dynaconf会完整复制这个结构,不会额外嵌套。
解决办法
这里有两种简单有效的方式来修复这个问题:
方法1:直接引用整个父节点
不要单独引用叶子节点,而是直接引用包含目标值的子节点,这样能完整继承结构,避免嵌套。修改你的配置如下:
[default.celery.google] domain = '@get google.domain' # 直接引用整个calendar节点,而不是单独的calendar_ids calendar = '@get google.calendar' [default.onion.google] domain = '@get google.domain' # 同样直接引用整个calendar节点 calendar = '@get google.calendar'
这样运行EXAMPLE_ENV=nonprod dynaconf -i dynaconf_example.settings get celery后,就能得到预期的结果:
{ "google": { "calendar": { "calendar_ids": ["a", "b"] }, "domain": "nonprod.example.org" } }
方法2:使用dynaconf_merge + @merge合并节点
如果你只需要合并部分内容,而不是引用整个节点,可以用dynaconf_merge配合@merge来实现:
[default.celery.google.calendar] # 启用合并模式 dynaconf_merge = true # 合并google.calendar下的所有内容 @merge = "google.calendar"
这种方式会把google.calendar下的所有键值对直接合并到当前的celery.google.calendar节点中,同样不会出现多余的嵌套。
补充说明
你之前尝试的dynaconf_merge之所以没起作用,是因为把它放在了全局环境节点(比如[default])下,而不是需要合并的具体子节点(比如[default.celery.google.calendar])中。只有在目标节点下设置dynaconf_merge = true,才能触发合并逻辑。
另外你提到的.py配置文件的类似问题,本质也是一样的:引用标量值时被意外包装成字典。对于列表这类非字符串类型,@format确实无法处理,所以最好的方式还是用上面两种方法,直接引用或合并整个节点。
备注:内容来源于stack exchange,提问作者Wil Cooley

