首页 > 编程问答 >Flask-WTF:如何在 Flask FormField 中定义自定义变量

Flask-WTF:如何在 Flask FormField 中定义自定义变量

时间:2024-07-25 04:37:48浏览次数:11  
标签:python flask flask-wtforms

我正在尝试在 Flask 中设置一个动态表单,其中该表单具有动态填充的 FormFields FieldList。虽然大部分都有效,但我不断遇到每个 FormField 的变量问题。我需要每个 FormField 有一个标签,它是 FormField 的名称(并在页面上呈现)和一个在显示/隐藏脚本中使用的自定义 ID,该脚本使用动态填充的 SelectField 来选择要显示和显示的子表单隐藏。但是,我无法让变量在提交表单后保留其状态,这也使我无法正确处理返回的数据。

这些是我的表单类:

class ColumnForm(Form):
    text = Label('', '')
    condition = SelectField('Condition', choices=[('eq', 'Equal to'), ('contains', 'Contains')], validators=[Optional()])
    value = StringField(validators=[Optional()])

class CategoryForm(Form):
    catName = ''
    Columns = FieldList(FormField(ColumnForm))
    def add_field(self, name):
        # I have tried several ways of adding the formFields to the FieldList, this is the only way I get the variables to be renamed, but I do not have a way to get the submitted data back
        if not self.checkIfformInFieldList(name):
            self.Columns.append_entry()#{'text' : name})
            self.Columns[-1].form.text = Label(len(self.Columns)-1, name)
            self.Columns[-1].name = name
            self.Columns[-1].id = name
            self.Columns[-1].form.condition.id = f'{name}-condition'
            self.Columns[-1].form.condition.name = f'{name}-condition'
            self.Columns[-1].form.value.name = name+'-value'
            self.Columns[-1].form.value.id = name+'-value'
            self.Columns[-1].form.value.validators = [Optional()] 
    def checkIfformInFieldList(self, name)->bool:
        for column in self.Columns:
            if column.name == name:
                return True
        return False

class baseForm(FlaskForm):
    table_select = SelectField('Select Table', choices=['Select Table'],validators=[Optional()])
    submit = SubmitField('Filter')
    tables = FieldList(FormField(CategoryForm))
    def add_category(self, catName:str, columnNames:list):
        self.tables.append_entry()
        self.tables[-1].name = catName
        self.tables[-1].id = catName
        for columnName in columnNames:
            self.tables[-1].add_field(columnName)

这是我的表单(的简化版本)初始化:

@app.route('/', methods=['GET', 'POST']))
def index():
    form = baseForm(request.form)
    databaseStructure = get_database_structure(db_dict)
    for table in databaseStructure:
        form.table_select.choices.append(table)
    if not form.tables.entries:
        for table, columns in databaseStructure.items():
            form.add_category(table, columns)
    if request.method == 'POST' and form.validate():
        print(form.data)
    return render_template('index.html', form = form)

这是我的 html 模板的(简化版本):


<form method="post">
    {{ form.hidden_tag() }}
    <p>
        {{ form.table_select.label }}<br>
        {{ form.table_select }}
    </p>
    {% for category in form.tables %}
    <div id = "{{ category.name }}">
        {% for column in category.Columns %}
        <p>
            {{ column.form.text }}
            {{ column.form.condition }}
            {{ column.form.value }}
        </p>{% endfor %}
</div>
{% endfor %}
    <p>{{ form.submit() }}</p>
</form>
<script>
    document.addEventListener('DOMContentLoaded', function () {
        const tableSelect = document.querySelector('#table_select');
        const columnSelect = document.querySelector('#column_select');
        tableSelect.addEventListener('change', function () {
            localStorage.setItem('selectedTable', tableSelect.value)
        });
    });
    window.onload = showFormFunction()
    document.getElementById("table_select").onchange = function() {showFormFunction()};
    function showFormFunction() {
        let table_select_value = document.getElementById("table_select").value;
        {% for tableName in form.tables %}{% if loop.index0 == 0 %}
        if (table_select_value == "{{ tableName.id }}"){ {% else %} else if (table_select_value == "{{ tableName.id }}"){ {% endif %}
            document.getElementById("{{ tableName.id }}").style.display = "inline"; {% for tableNamex in form.tables %} {% if tableName.id != tableNamex.id %}
            document.getElementById("{{ tableNamex.id }}").style.display = "none"; {% endif %} {% endfor %}
        }{% endfor %} else { {% for tableName in form.tables %}
            document.getElementById("{{ tableName.id }}").style.display = "none";{% endfor %}
        }
        
    };
</script>

遇到的问题是,在每次请求时都会重新创建 Flask-WTF 表单及其字段,这意味着在 add_field 方法中设置的任何自定义属性都会在下次服务器收到请求时丢失。

为了解决这个问题,可以使用以下方法之一:

1. 使用隐藏字段存储自定义变量:

可以为每个 ColumnForm 实例添加隐藏字段,以存储 name id 值。然后,可以在呈现表单和处理提交的数据时访问这些隐藏字段。

```python class ColumnForm(Form): text = Label('', '') condition = SelectField('Condition', choices=[('eq', 'Equal to'), ('contains', 'Contains')], validators=[Optional()]) value = StringField(validators=[Optional()]) # 添加隐藏字段来存储自定义变量 name = HiddenField() id = HiddenField()

# 在 add_field 方法中设置隐藏字段的值 self.Columns[-1].form.name.data = name self.Columns[-1].form.id.data = name ```

在 HTML 模板中,需要渲染隐藏字段:

```html {% for column in category.Columns %}

{{ column.form.text }} {{ column.form.condition }} {{ column.form.value }} {{ column.form.name }} {{ column.form.id }}

{% endfor %} ```

在处理表单提交时,可以从隐藏字段中访问 name id 值。

2. 使用动态创建字段的名称:

可以在创建字段时使用动态生成的名称,并在处理表单提交时使用这些名称来访问相应的值。

```python class CategoryForm(Form): # ...

   def add_field(self, name):
       # ...
       # 使用动态生成的名称创建字段
       self.Columns.append_entry({
           'text': Label(len(self.Columns)-1, name),
           'condition': SelectField('Condition', choices=[('eq', 'Equal to'), ('contains', 'Contains')], validators=[Optional()], name=f'{name}-condition', id=f'{name}-condition'),
           'value': StringField(validators=[Optional()], name=f'{name}-value', id=f'{name}-value')
       })

# 在处理表单提交时,使用动态生成的名称访问字段的值 for category in form.tables: for column_name in category.Columns.data: condition_value = category.data[f'{column_name}-condition'] value = category.data[f'{column_name}-value'] ```

这种方法不需要隐藏字段,但代码可能更难阅读和维护。

3. 使用 JavaScript 处理表单数据:

可以使用 JavaScript 在客户端处理表单数据,并在提交表单之前添加必要的自定义变量。

javascript // 在提交表单之前修改表单数据 const form = document.querySelector('form'); form.addEventListener('submit', (event) => { // ... 添加自定义变量到表单数据 form.submit(); });

这种方法可以使的 Python 代码更简洁,但需要更多 JavaScript 代码。

选择最适合的方法取决于的具体需求和编码风格。

标签:python,flask,flask-wtforms
From: 78461420

相关文章

  • 用于打印脚本输出的 Python 实用程序
    我可以发誓有一个实用程序可以打印一个python脚本,其输出交织在一起。例如,给定一个脚本:a=2b=3print(a+b)print(a*b)该实用程序将输出a=2b=3print(a+b)#>5print(a*b)#>6有人知道该实用程序的名称吗?我最难找到它。谢谢你!描述的实用程序没有标......
  • a method to make some handy tools with python
    Inmyworkingofcomputer,therearealotofsimplejobsthatarefrequentlyrepeated.Itriedtofindawaytomakethesejobbeenprocessedeasily.Method1:Themethodiswritingascripttodothejob,andexecutingthescriptbyutoolsextensionuto......
  • Python网络爬虫详解:实战豆瓣电影信息采集
    文章目录前言一、爬虫是什么?二、常用库及其作用1.Requests2.BeautifulSoup3.lxml4.Scrapy5.Selenium6.PyQuery7.Pandas8.JSON9.Time三、实现步骤步骤一:环境准备步骤二:数据采集步骤三:数据处理步骤四:数据存储总结前言随着互联网的迅猛发展和数据分析需求的不......
  • python学习之内置函数
    Python拥有许多内置函数,这些函数是Python的一部分,不需要额外导入即可直接使用。这些函数提供了对Python解释器功能的直接访问,涵盖了从数学计算到类型检查、从内存管理到异常处理等各个方面。下面是一些常用的Python内置函数及其简要说明:一、Printprint函数大家都不会......
  • Python中以函数为作用域
    点击查看代码#第一题foriteminrange(10):#不报错,没有函数,所有操作在全局作用域里面执行,item最后赋值为:9,此时item在缩进与全局都可以使用passprint(item)#第二题item=10deffunc():foriteminrange(10):#优先在本地查找,找不到在到全局查找p......
  • 掌握IPython宏:%%macro命令的高效使用指南
    掌握IPython宏:%%macro命令的高效使用指南在编程中,宏是一种允许你定义可重用代码片段的强大工具。IPython,这个增强版的Python交互式环境,提供了一个名为%%macro的魔术命令,允许用户创建宏,从而提高代码的可重用性和效率。本文将详细介绍如何在IPython中使用%%macro命令创建宏,并......
  • 7月24号python:库存管理
    7月24号python:库存管理题目:​ 仓库管理员以数组stock形式记录商品库存表。stock[i]表示商品id,可能存在重复。原库存表按商品id升序排列。现因突发情况需要进行商品紧急调拨,管理员将这批商品id提前依次整理至库存表最后。请你找到并返回库存表中编号的最小的元素以便及......
  • IPython的Bash之舞:%%bash命令全解析
    IPython的Bash之舞:%%bash命令全解析IPython的%%bash魔术命令为JupyterNotebook用户提供了一种在单元格中直接执行Bash脚本的能力。这个特性特别适用于需要在Notebook中运行系统命令或Bash特定功能的场景。本文将详细介绍如何在IPython中使用%%bash命令,并提供实际的代码示......
  • Python数据分析与可视化大作业项目说明(含免费代码)
    题目:对全球和中国互联网用户的数据分析与可视化代码下载链接:https://download.csdn.net/download/s44359487yad/89574688一、项目概述1.1.项目背景:互联网是当今时代最重要和最有影响力的技术之一,它已经深刻地改变了人们的生活、工作、学习等方面。互联网用户数据是反映......
  • IPython的跨界魔术:%%javascript命令深度解析
    IPython的跨界魔术:%%javascript命令深度解析IPython,作为Python编程的强大交互式工具,提供了多种魔术命令来扩展其功能。其中,%%javascript魔术命令允许用户在IPythonNotebook中直接执行JavaScript代码,打通了Python和JavaScript两个世界,为数据可视化、Web内容操作等提供了便......