使用jquery动态更新selectfield选项后验证WTForm

hgncfbus  于 2023-10-17  发布在  jQuery
关注(0)|答案(2)|浏览(89)

我正在创建一个flask应用程序,并使用WTForms创建了一个表单。该表单有两个SelectFields(下拉菜单)和一个提交按钮。我想下拉菜单是动态的-基本上,用户将选择一个选项,从CNOAA,这将触发在后台的数据库查询,将返回CNOB的选择。
我已经找到了一些很好的解决办法

最后,我使用链接的stackoverflow问题的第二个答案来模拟我的解决方案。其基本思想是jQuery调用一个flask端点,该端点执行数据库查询,并返回动态填充的新选项
我想在表单提交后进行一些额外的处理,为此,我在索引端点中使用if form.validate_on_submit():来 Package 额外的处理并验证表单。我找到的这个问题的答案都没有试图验证这个形式。问题是,XNUB上的choices字段现在无效。我从一些默认值开始,这是验证器函数所期望的,然后使用jquery动态更新选择,而不更新选择。如解决方案中所述,数据库查询是在与我检查表单验证的索引端点不同的端点中处理的,因此它无法访问这些新选项来填充它们。
在索引端点中更新表单的选项(在选项被更新之后)以使表单在提交时有效的最佳方法是什么?
一些代码片段
jquery(主要是从链接的stackoverflow答案中复制的)

<script type="text/javascript">
      $(document).ready(function() {

        $('#dropdown_one').change(function(){

          $.getJSON('/_update_dropdown', {
            selected_class: $('#dropdown_one').val()

          }).done(function(data) {
                $('#dropdown_two').html(data.html_string_selected);
           })
        });
      });
    </script>

窗体类

class Form(FlaskForm):
    dropdown_one = SelectField("Choose an option", choices = [options])
    dropdown_two = SelectField("Choose option based on dropdown one")
    submit = SubmitField("Submit")

python/flask索引端点

@bp_views.route('', methods=["POST", "GET"])
def index():        
    form = Form()

    form.dropdown_two.choices = [(None, "Choose item on dropdown one first")] # default value for the second dropdown
        
    if form.validate_on_submit():
        # further processing
        # this check fails because the choices have been updated from the default values and the choice isn't valid
    

    return render_template('index.html', form=form)

python/flask更新端点(主要从链接的stackoverflow应答中复制

@bp_views.route('/_update_dropdown')
def update_dropdown():
    # the value of the first dropdown (selected by the user)
    selected_class = request.args.get('selected_class', type=str)
    
    # get values for the second dropdown
    updated_values = db.fetch_data(selected_class)

    # create the value sin the dropdown as a html string
    html_string_selected = ''
    for entry in updated_values:
        html_string_selected += '<option value="{}">{}</option>'.format(entry, entry)

    return jsonify(html_string_selected=html_string_selected)
pod7payv

pod7payv1#

我也遇到了这个问题。我的解决方案是在提交时动态创建所选选项,以便它可以有效。
这是它如何工作的一个例子:

if request.method == 'POST':
    for k,v in form.data.items():
        if isinstance(form[k].widget, wtforms.widgets.Select):
            form[k].choices = [(form[k].data, form[k].data)]

    if form.validate_on_submit():

应该注意的是,在本例中,SelectFields绕过了验证。恶意行为者可以提交他们想要的任何值,并且在提交时它将变得有效,除非采取额外的服务器端步骤来限制可以创建的选择。

gv8xihay

gv8xihay2#

正如Jonathan狄克逊提到的,在帖子中做出选择并将validate_choice设置为False可能会导致恶意数据
我认为,要解决这个问题,您可以将validate_choice设置为False,然后在POST端点更新选项值,最后将validate_choice设置回True并调用validate_on_submit

form(FlaskForm):
    SelectField("Choose option based on dropdown one", validate_choice=False)

form.catalogue_id.choices = [(1, 'hi'), (2, 'hi2')] # use query to get data
form.catalogue_id.validate_choice = True
print(form.validate_on_submit())

请,如果这不安全,这将是很好的注意,通过评论我的回答

相关问题