【问题标题】:Separate presentation from logic with WTForms使用 WTForms 将表示与逻辑分开
【发布时间】:2014-03-28 02:23:05
【问题描述】:

我只是熟悉 Flask、WTForms(和 flask-WTF)。我觉得我错过了什么。

根据WTForms docs“可以为您生成表单字段HTML,但我们允许您在模板中自定义它。这允许您保持代码和表示的分离,并将那些杂乱的参数排除在您的python之外代码。”

建议的 HTML 单选输入建模方法是:

class ExmapleForm(Form):
    language = RadioField(u'Programming Language', choices=[('py', 'Python'), ('js', 'JavaScript')])

....模板 HTML 单选输入的建议方法是:

{% for subfield in form.radio %}
    <tr>
        <td>{{ subfield }}</td>
        <td>{{ subfield.label }}</td>
    </tr>
{% endfor %}

使用这种方法,choices 属性“这是(值、标签)对的序列”不是将表示与模型混合在一起吗?

有没有办法将标签移动到模板上并与值匹配?

【问题讨论】:

    标签: python flask wtforms flask-wtforms


    【解决方案1】:

    有趣的问题。如果我们从 MVC 模式的角度来考虑,我认为下拉列表中的选项列表属于模型,而不是视图。所以我不会让设计者在模板中定义这些选择。我相信我们同意这一点,对吧?

    将选项列表硬编码在您的示例中的表单中会更好,但这也不理想。大概你有一个Language 模型或类似的实体,对吗?该模型是有效编程语言选择的权威,因此它应该是向任何人提供有效选择列表的模型,无论是表单还是其他子系统。

    正如您在问题中提到的,每个选项都有一个内部名称和一个显示名称。由于我们讨论的是显示字符串,所以不要忘记您的字段的 u'Programming Language' 标题属于显示字符串的同一类别。这些字符串应该是模板设计者的责任吗?我不知道,这是模型和演示之间的灰色地带,我认为设计师应该对事物的外观有权威,而不是对内容。

    如果您想更好地控制这些显示字符串的外观,您可以使用 gettext 之类的翻译工具包(例如,通过 Flask-Babel)。如果您的应用程序通过 gettext 呈现文本,您可以将代码或模板中的任何字符串映射到其他字符串。这用于翻译成其他语言,但您也可以使用它来单独控制字符串在应用程序的本地语言中的显示方式。映射是在外部数据文件中完成的,所以我认为这实现了您正在寻找的独立性。

    【讨论】:

    • 感谢您的反馈和建议 Flask-Babel....我会考虑将其作为一个选项。询问时,我想确保我没有遗漏 WTForms 的一些明显内容。作为旁注,感谢您关于 Flask 的文章....我读过一些 ;-)
    【解决方案2】:

    从纯理论的角度来看,这似乎不是一个好主意。如果您必须将标签与模板中的实际值连接起来,那么这将意味着模板中有业务逻辑。

    此外,您如何设想执行此操作的确切代码?它需要分配标签的语句中的子字段上下文。我无法想象模板中的代码看起来不错。它会成为表示逻辑的一部分吗?

    【讨论】:

    • 好问题。我是从另一个角度来的……要求设计师编辑您的模型以更新模板(标签)听起来也是个坏主意。
    • 不能 {{ form.radio.value }} 工作? ....我想您应该知道模板中每个无线电输入的值,这可能并不理想
    • 我明白了:)。好吧,我想底线是开发人员/设计师的工作总是有联系点。每个 Web 框架都以不同的方式处理它,但一些冲突是不可避免的。
    • {{ form.radio.value }} 打印整个字段?然后你在框架代码中有演示代码( 等)......
    • 是的,不能 {{ form.language.py }} 或 {{ form.language['py'] }} 转换为 。工作量很大,但收效甚微……但 WTForms 提供的表单验证让这一切变得物有所值。
    【解决方案3】:

    这是我想出的解决方案(保持分离)。这可能有点矫枉过正,但我​​会尝试一下,看看它是如何扩展的。

    在forms.py中:

    import sys
    sys.path.append("templates")
    import constants
    
    class ExmapleForm(Form):
        language = RadioField('language', choices=constants.languages['choices'], validators=constants.languages['validators'])
    

    然后我在模板文件夹中创建了一个名为 constants.py 的文件:

    from wtforms.validators import InputRequired
    
    languages = {
        'choices': [
            ('py', 'Python'),
            ('js', 'JavaScript')
        ],
        'validators': [
            InputRequired(message = 'Please Select')
        ]
    }
    

    希望它有所帮助(并解决)

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签