【问题标题】:How do I pass a variable from a function to a WTForm? I use the variable to choose RadioField choices如何将变量从函数传递到 WTForm?我使用变量来选择 RadioField 选项
【发布时间】:2019-04-21 01:10:00
【问题描述】:

我正在尝试将会话变量传递到 WTForm。我使用变量来选择 RadioField 条目。

我尝试将其作为常规变量传递,但 WTForm 无法识别该变量。我尝试了不同的论点,但它仍然无法在 WTForms 中识别它。这是我要传递的变量级别。我知道如果我在 ZWOForm(Form) 类的第一行写 level = 1(或 2 或 3),这一切都有效:我错过了什么?

来自 init.py

class ZWOForm(Form):
    zwotitle = TextField('Title', [validators.Length(min=3, max=50)])
    zwotags = TextField('Tags', [validators.Length(min=3, max=50)])
    category = TextField('Category (Your Choice)', [validators.Length(min=3, max=50)])
    if level <3:
        if level <2:
            zwolevel = RadioField('Viewing Level', choices=[('1','Public')], default=1)
        else:
            zwolevel = RadioField('Viewing Level', choices=[('1','Public'),('2','Private')], default=1)
    else:
        zwolevel = RadioField('Viewing Level', choices=[('1','Public'),('2','Private'),('3','Team')], default=1)
        zwodescription = TextAreaField('Description', [validators.Length(min=3, max=200)])      


@app.route('/createzwo/', methods=["GET","POST"])
@login_required
def create_zwo():
    try:
        level = session['level']
        form = ZWOForm(request.form)
        if request.method == "POST" and form.validate():
...
        return render_template("createzwo.html", form=form)

来自 HTML 表单:

{% from "_formhelpers.html" import render_field %}
<form method=post action="/createzwo/">
    <dl>
        {{render_field(form.zwotitle)}}
        {{render_field(form.zwotags)}}
        {{render_field(form.category)}}
        {{render_field(form.zwolevel)}}
        {{render_field(form.zwodescription)}}
    </dl>
    <p><input type=submit value="Create ZWO File"></p>
</form>

来自 _formhelpers.html:

{% macro render_field(field) %}
    <dt>{{ field.label }}
    <dd>{{ field(**kwargs)|safe }}
        {% if field.errors %}
            <ul class=errors>
            {% for error in field.errors %}
                <li>{{ error }}</li>
            {% endfor %}
            </ul>
        {% endif %}
    </dd>
{% endmacro %}

我看到的错误是“级别”未定义,渲染错误会导致我们的一堆行指向其他 .py 文件(本地和全局)。

【问题讨论】:

    标签: python-2.7 flask-wtforms


    【解决方案1】:

    表单的类定义中的代码仅在模块最初加载时执行一次,此时局部变量 level 不存在。即使它确实存在,您也只会设置一次类定义,而您希望能够在每次显示时更改表单选择。这可以在您的视图函数中轻松实现。不要在表单类中设置字段选择,而是在表单创建后通过设置字段选择属性的值将它们设置在表单本身上。鉴于每个级别可用的选项数量恰好等于该级别的值,您可以使用列表切片来生成此列表。

    class ZWOForm(Form):
        zwotitle = TextField('Title', [validators.Length(min=3, max=50)])
        zwotags = TextField('Tags', [validators.Length(min=3, max=50)])
        category = TextField('Category (Your Choice)', [validators.Length(min=3, max=50)])
        zwolevel = RadioField('Viewing Level', choices=[], default=1)
        zwodescription = TextAreaField('Description', [validators.Length(min=3, max=200)])      
    
    @app.route('/createzwo/', methods=["GET","POST"])
    @login_required
    def create_zwo():        
        try:
            form = ZWOForm(request.form)
            all_choices = [('1','Public'),('2','Private'),('3','Team')]
            choices = all_choices[:session["level"]]
            form.zwolevel.choices = choices
    
            if request.method == "POST" and form.validate():
                ...
            return render_template("createzwo.html", form=form)
    

    【讨论】:

    • 抱歉,zwodescriotion 在每个版本上,就在 zwo 级别选项的下方。这只是一个更长的表格的顶部。我将不得不吸收您提供的动态版本,因为我不会自然地“看到”它。这可能是一个更好的选择。我将不得不更多地使用它并让你知道。
    • 鉴于您只想更改单选框选项而不是添加/删除字段,我已经编辑了答案以反映这一点。希望它现在应该更简单,更容易理解。
    • 是的,我可以看到你在用代码做什么。但是,当我应用它时出现以下错误:切片索引必须是整数或 None 或具有 index 方法。 “level”是一个整数,但是all_choices或者choices可能有问题抛出错误?
    • 听起来您将级别存储为字符串而不是会话中的整数。试试choices = all_choices[:int(session["level"])]
    • 我发现会话变量实际上没有任何属性。因此,我将其强制为整数,一切正常!非常感谢您的帮助!
    猜你喜欢
    • 2018-05-20
    • 1970-01-01
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多