如何使用Cookiecutter整洁渲染带选项的YAML数组?
嘿,我完全懂你那种被嵌套if支配的痛苦!针对这种多选项生成列表的场景,其实有两种更清爽的实现方式,不用写一堆嵌套判断:
方法1:用预处理钩子(推荐复杂场景)
Cookiecutter支持Python钩子,你可以在hooks/pre_gen_project.py里提前收集用户选中的数据库,然后把结果传到模板上下文里,这样模板里的逻辑就超级简单了。
步骤1:添加预处理钩子
在你的模板根目录创建hooks/pre_gen_project.py,写入以下代码:
def main(): # 从Cookiecutter上下文获取用户选择 selected_dbs = [] if cookiecutter["mysql"] == "yes": selected_dbs.append("mysql") if cookiecutter["postgres"] == "yes": selected_dbs.append("postgres") # 验证:禁止全选no的情况 if not selected_dbs: raise ValueError("⚠️ 请至少选择一个支持的数据库!") # 将结果存入上下文,供模板使用 cookiecutter["supported_databases"] = selected_dbs if __name__ == "__main__": main()
步骤2:简化模板中的YAML
你的YAML模板文件可以直接写成这样,完全不用复杂判断:
supported_databases: {% for db in supported_databases %} - {{ db }} {% endfor %}
方法2:直接在Jinja2模板内处理(适合简单场景)
如果不想用钩子,也可以直接在YAML模板里用Jinja2的列表操作来实现,比嵌套if简洁很多:
supported_databases: {% set selected_dbs = [] %} {% if mysql == 'yes' %}{% do selected_dbs.append('mysql') %}{% endif %} {% if postgres == 'yes' %}{% do selected_dbs.append('postgres') %}{% endif %} {% if selected_dbs %} {% for db in selected_dbs %} - {{ db }} {% endfor %} {% else %} {% raise "错误:必须至少选择一个数据库!" %} {% endif %}
额外优化:避免全选no的前置验证
除了上面代码里的验证,你还可以在cookiecutter.json里设置默认值,确保用户至少有一个选项默认是yes,从源头减少无效配置:
{ "mysql": ["yes", "no"], "postgres": ["yes", "no"], "_default": { "mysql": "yes" } }
这两种方法都能帮你摆脱嵌套if的困扰,钩子方法更适合后续扩展(比如新增数据库选项时,只需要在钩子里加一行判断),模板内处理则更轻量。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

