csrf_token包含在表格中。

问题描述 投票:0回答:1

在我的Flask应用程序中,我的validate_on_submit()方法有以下问题。

快速概述我的情况。

我的表单类是根据输入动态创建的。

class EditUsers(FlaskForm):

    submit = SubmitField('Submit')

def form_builder(roles_list):

    class EditUsersForm(EditUsers):
        pass

    for role in roles_list:
        if isinstance(role, tuple) and len(role) == 5:
            if not role[2] and role[3]:
                setattr(EditUsersForm, f'{role[0]}_{role[4]}_bool', BooleanField(label=role[0]))
                setattr(EditUsersForm, f'{role[0]}_{role[4]}_date', SelectField('Expiration Period', choices=choices))
        else:
            raise IncorrectType

IncorrectType是我准备的自定义Exception,选择是在同一个文件中使用datetime创建的(这无关紧要,所以我没有把它包含在代码中)。

我在flask应用中的路线(简化)。

#### EDIT: I pasted the wrong route, POST and GET Methods are included###
@edit_users.route('/users', methods=['GET', 'POST'])

def users():
...  # Some code there
form = form_builder(roles_to_form)

print(form.is_submitted())
print(form.validate())
print(form.validate_on_submit())

return render_template('edit_user.html',
                       data_dict=data_dict,  # in data_dict i pass form fields names and some other data
                       form=form,
                       )

我的模板。

<!-- Some usual stuff goes there css js etc -->

<div >
    <form class="form form-horizontal" method="post" role="form" style="margin: auto; text-align: center; width: 40%;">
        {{ form.csrf_token() }}
        <table class="table" align="center">
            <thead>
                <th>Role</th>
                <th>Expiration Date</th>
                <th>Give Role?</th>
            </thead>
            {% for field in data_dict['id_list'] %}
            <tr>
                <td align="left">{{ field[2] }}</td>
                <td align="left">
                    {{ form[field[1]] }}
                </td>
                <td align="left">{{ form[field[0]] }}</td>
            </tr>
            {% endfor %}
            <tr>
                <td colspan="3" align="center">{{ form.submit() }}</td>
            </tr>
        </table>
    </form>
</div>

我的问题是什么?

当我点击提交按钮的时候。is_submitted() 返回True,但 validate() 没有,因此我不能使用典型的 if form.validated_on_submit() 因为即使在我提交表格时,它也会返回False。

我挖了一下,发现了一些不寻常的地方。我使用了表单属性的受保护成员,来检查任何被validate()函数视为输入的内容。

for name in form._fields:
    print(name)
    inline = getattr(form.__class__, 'validate_%s' % name, None)
    print(inline)

输出(不要介意字段名):

"提交

工程师_2_bool

工程师_2_日期

操作员_3_bool

运营商_3_日期

监管员_4_bool

监事_4_日期

访客_5_bool

访客_5_日期

csrf_token

我不知道为什么我的表格里没有出现 validate_{name} 属性。

python-3.x flask jinja2 flask-wtforms wtforms
1个回答
1
投票

我根据你的代码做了一个工作示例,结果出现了你描述的问题。

如果我把你的代码反转过来,似乎是这样的 form[field[1]] 是你的BooleanField或SelectField。所以要在模板中呈现它,你必须使用 form[field[1]]() (也可以使用render_field).所以:

<tr>
    <td align="left">{{ field[2] }}</td>
    <td align="left">
        {{ form[field[1]] }}
    </td>
    <td align="left">{{ form[field[0]] }}</td>
</tr>

纠正为.NET Framework 2.0。

<tr>
    <td align="left">{{ field[2] }}</td>
    <td align="left">
        {{ form[field[1]]() }}
    </td>
    <td align="left">{{ form[field[0]]() }}</td>
</tr>

https:/flask.palletsprojects.comen1.1.xpatternswtforms#forms-in-templates。

由于您使用的是FlaskForm,在您的模板中,您必须替换掉 {{ form.csrf_token() }}{{ form.csrf_token }}https:/flask-wtf.readthedocs.ioenstablecsrf.html#html-表单。[编辑 没有任何区别]

[在w8eight的评论后编辑]该路由没有被授权进行POST(并且该表单提出了一个POST请求,如在 <form class="form form-horizontal" method="post" [...].所以你必须改变: @edit_users.route('/users', methods=['GET']) 变成 @edit_users.route('/users', methods=['GET','POST'])


0
投票

问题出在传递给选择的数据类型上。SelectField. 我通过带有 datetime.datetime 到它。当改变类型为 str 一切都很顺利。

© www.soinside.com 2019 - 2024. All rights reserved.