首页 > 编程问答 >从前端向 FlaskForm 添加多个 WTF 字段

从前端向 FlaskForm 添加多个 WTF 字段

时间:2024-08-09 02:55:46浏览次数:10  
标签:python flask wtforms

我想制作一个字段数量不稳定的表单,以便用户可以根据需要添加尽可能多的新字段。 在不提前知道字段数量的情况下,如何获取 Python 端的所有表单数据(通过 WTForms)?

forms.py

class Form(FlaskForm):
    field = StringField('field')
    submit = SubmitField('submit')

HTML

<!-- I want my form to be viewed in Bootstrap Modal. -->

<div class="modal" tabindex="-1">
  <div class="modal-body">

    <form name="create-form" method="POST">
      <div class="input-group">
        {{ form.hidden_tag() }}
        {{ form.field(class="form-control") }}
        <!-- The place to insert additional fields -->
    
        {{ form.submit(class="btn btn-outline-secondary) }}
      </div>
    </form>
    <button id="add" type="button" class="btn btn-outline-secondary">Add</button>

  </div>
</div>

<template id="new-field">
  {{ form.field(class="form-control") }}
</template>

JS

modal.querySelector('#add').addEventListener('click', (ev) => { 
    modal.querySelector(/*Place to insett*/).before(/*new field from <template>*/);
});

modal.querySelector('form').addEventListener('submit', async (ev) => {
    ev.preventDefault();
    let form = modal.querySelector('form');
    let resp = await fetch('/ajax', {method: 'POST', body: new FormData(form)});
});
                       
routes.py

@bp.route('/ajax', methods=['GET', 'POST'])
def ajax():
    # request.form contains all values 
    form = Form()
    
    if form.validate():
        # form.data has the only one value (from first field)
        return {}
    return {}

是的,似乎我需要为每个输入提供唯一的 wtf 字段。好吧,回到绘图板。

forms.py

class Form(FlaskForm):
    field = StringField('field')
    submit = SubmitField('submit')

    def add_filed(self, i):
        field = StringField(f'field{i}')
        setattr(self.__class__, f'field{i}', field)
        return self.__class__()
            
HTML

<template id="new-field">
  {{ form.add_field(7)|attr("field7")(class="form-control") }}
</template>

什么也没有。 TypeError: 'UnboundField' object is not callable

再一次尝试:

modal.querySelector('#add').addEventListener('click', async (ev) => {
    // At this point I'm sending ajax-request to call Form.add_field(7)
    // on the Python side, bu as result I got {'field': 'value', 'field7': None}.
    modal.querySelector(/*Place to insett*/).before(/*new field from <template>*/);
});

我错过了什么? 我读过很多有关此的主题,但没有明白。

谢谢。


遇到的问题源于 Flask-WTF 表单在服务器端生成,而尝试在客户端动态添加字段。尽管尝试动态添加字段,但服务器并不知道这些更改,因此它只处理最初在表单定义中指定的字段。

为了解决这个问题,需要采取不同的方法:

1. 使用 JavaScript 处理动态字段:

  • 不要试图动态添加 WTF 字段。 让的 JavaScript 代码将所有动态添加的字段的名称和值存储在一个数组或对象中。
  • 在表单中添加一个隐藏字段, 用于存储 JavaScript 生成的动态字段数据(例如,作为一个 JSON 字符串)。
  • 在服务器端, 从隐藏字段中检索动态字段数据,并将其解析为 Python 数据结构(例如,列表或字典)。

示例代码:

HTML ( templates/index.html ):

<div class="modal" tabindex="-1">
  <div class="modal-body">
    <form name="create-form" method="POST">
      <div class="input-group">
        {{ form.hidden_tag() }}
        {{ form.csrf_token }} 
        {{ form.field(class="form-control") }} 
        <div id="dynamic-fields"></div>
        <button type="button" id="add" class="btn btn-outline-secondary">Add</button>
        {{ form.submit(class="btn btn-outline-secondary") }}
      </div>
    </form>
  </div>
</div>

<template id="new-field-template">
  <div class="input-group">
    <input type="text" name="dynamic_fields[]" class="form-control">
  </div>
</template>

<script>
  const addButton = document.getElementById('add');
  const dynamicFieldsContainer = document.getElementById('dynamic-fields');
  const newFieldTemplate = document.getElementById('new-field-template');

  addButton.addEventListener('click', () => {
    const newField = newFieldTemplate.content.cloneNode(true);
    dynamicFieldsContainer.appendChild(newField);
  });
</script>

Python ( forms.py ):

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField

class MyForm(FlaskForm):
    field = StringField('Field')
    submit = SubmitField('Submit')

Python ( routes.py ):

from flask import render_template, request, jsonify
from .forms import MyForm

@app.route('/', methods=['GET', 'POST'])
def index():
    form = MyForm()
    if form.validate_on_submit():
        static_field = form.field.data
        dynamic_fields = request.form.getlist('dynamic_fields[]') 

        # 处理表单数据...
        print("Static Field:", static_field)
        print("Dynamic Fields:", dynamic_fields)

        return jsonify({'message': 'Form submitted successfully!'})
    return render_template('index.html', form=form)

解释:

  1. JavaScript 动态添加字段: 当用户点击 "Add" 按钮时,JavaScript 会克隆一个新的输入字段并将它添加到 dynamic-fields 容器中。所有动态添加的字段都使用相同的名称 dynamic_fields[] ,以便在服务器端方便地检索。
  2. 服务器端处理动态数据: 在 Flask 路由中, request.form.getlist('dynamic_fields[]') 用于获取所有名为 dynamic_fields[] 的字段的值,并将它们存储在一个列表中。

通过这种方法,可以有效地处理动态添加的表单字段,并将其数据发送到 Flask 服务器进行处理。

标签:python,flask,wtforms
From: 78849996

相关文章

  • Python 类型提示:显式排除无效的重载组合?
    我有一个带有两个参数的函数,每个参数都可以采用两种类型之一。四个成对组合中的三个有效,但第四个无效。我想找到一种方法来键入提示此场景,可以检查这些类型,但不一定每次调用foo()时都必须编写代码来检查无效情况。有没有办法可以改进foo()、bar()或两......
  • 我在制作 python 语音应用程序时遇到错误
    我编写了一个语音聊天应用程序代码,但是当我们运行此代码并加入语音频道时,我收到照片中的错误错误1错误2这是我的代码;客户端代码:importtkinterastkfromtkinterimportmessageboximportpyaudioimportsocketimportthreadingimporttimeHOST=......
  • 如何在 Flask 中启用 CORS
    我正在尝试使用jquery发出跨源请求,但它一直被拒绝并显示消息XMLHttpRequest无法加载http://...No'Access-Control-Allow-Origin'标头存在于所请求的资源上。起源...因此不允许访问。我正在使用flask、heroku和jquery客户端代码如下所示:$(documen......
  • pyocr,一个超酷的Python库!
    pyocr是一个用于光学字符识别(OCR)的Python库,它提供了一个简单的接口,允许开发者将图片中的文本提取出来。这个库是对Tesseract-OCR的封装,使得在Python环境中使用OCR技术变得更加便捷。如何安装pyocr首先,要使用pyocr库,您需要安装它。可以使用pip包管理工具来进......
  • pattern,一款超牛的Python库
    在程序开发中,处理文本数据和进行自然语言处理是常见需求。pattern是一个强大的Python库,专为文本分析而设计,提供了丰富的功能,包括自然语言处理、数据挖掘和网络分析等。它简单易用,让程序员能够快速实现复杂的文本处理任务。如何安装pattern在开始使用pattern库之前,首先......
  • 【Playwright+Python】系列教程(八)鉴权Authentication的使用
    写在前面还是有些絮叨的感觉,官方翻译和某些博主写那个玩楞,基本都是软件直接翻译后的产物。读起来生硬不说,甚至有的时候不到是什么意思,真的是实在不敢恭维。到底是什么意思?就是你已经登陆过一次,在Session、Cookie未失效的情况下,登录过一次后,下次就不用再走一遍登录的过程,从而缩......
  • 基于CNN-GRU-Attention混合神经网络的负荷预测方法(Python代码实现)
    ......
  • Python和AI库NumPy(二):数组创建与操作的深入探索
    目录1.数组创建1.1基本数组创建1.2使用内置函数创建数组1.3特殊数组的创建2.数组的基本操作2.1数组属性2.2数组索引和切片2.3数组的形状操作2.4数组拼接与分割3.数组的数学操作3.1基本算术操作3.2广播机制3.3线性代数运算4.高级数组操作4.1花式......
  • 如何为本地python共享文件网页配置公网地址实现跨网络远程访问
    文章目录前言1.本地文件服务器搭建1.1.Python的安装和设置1.2.cpolar的安装和注册2.本地文件服务器的发布2.1.Cpolar云端设置2.2.Cpolar本地设置3.公网访问测试4.结语前言本文主要介绍如何在Windows系统电脑上使用python这样的简单程序语言,在自己的电脑上搭建一个......
  • 基于YOLOv10深度学习的交通信号灯检测识别系统【python源码+Pyqt5界面+数据集+训练代
    《博主简介》小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~......