You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WTForms Dynamic Fields遇Request无post属性的AttributeError问题

解决WTForms Dynamic Fields中AttributeError: 'Request' object has no attribute 'post'错误

错误根源

Flask的request对象不存在post属性,你在代码中错误使用了request.post;同时当前代码仅在GET请求时处理动态字段,POST请求时未同步处理,会导致表单提交时动态字段的验证或数据获取失败。

修正后的完整代码

路由处理函数

from datetime import datetime, timedelta
from flask import request, redirect, url_for, flash, render_template
from flask_login import login_required, current_user
from wtforms import StringField

@app.route("/create", methods=["POST", "GET"])
@login_required
def create():
    # 统一创建动态表单结构,GET/POST请求都执行
    cfv = customfields.find({"_id": current_user.user_json['_id']})
    dynamic = WTFormsDynamicFields()
    
    for value in cfv:
        if value['fieldType'] == "Text Field":
            dynamic.add_field(value['fieldName'], value['fieldName'], StringField)
    
    if request.method == "POST":
        # POST请求传入request.form处理表单数据
        form = dynamic.process(CreateRecord, request.form)
        if form.validate_on_submit():
            # 从表单对象获取所有字段值(含动态字段)
            name = form.name.data
            phone = form.phone.data
            email = form.email.data
            company = form.company.data
            frequency = form.frequency.data
            datefc = form.date.data
            adate = datetime.today()

            # 计算下次联系时间
            if frequency == "Weekly":
                nContactTime = datefc + timedelta(days=7)
            elif frequency == "Monthly":
                nContactTime = datefc + timedelta(days=30)
            elif frequency == "Quarterly":
                nContactTime = datefc + timedelta(days=90)
            
            # 收集动态字段数据
            dynamic_fields_data = {}
            for field_info in cfv:
                if field_info['fieldType'] == "Text Field":
                    field_name = field_info['fieldName']
                    dynamic_fields_data[field_name] = getattr(form, field_name).data

            # 插入数据库,包含动态字段
            people.insert_one({
                "name": name, 
                "phone": phone, 
                "email": email, 
                "company": company, 
                "frequency": frequency,
                "parentrecord": current_user.user_json['_id'], 
                "dateadded": adate.strftime("%x"),
                "datefc": datefc, 
                "nextContact": nContactTime,
                **dynamic_fields_data
            })

            flash('记录已成功添加。')
            return redirect(url_for('profile'))
    else:
        # GET请求无需传入表单数据
        form = dynamic.process(CreateRecord)
    
    return render_template('create.html', form=form, auth=current_user.is_authenticated)

表单类(保持不变)

from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, DateField, SubmitField
from wtforms.validators import DataRequired

class CreateRecord(FlaskForm):
    name = StringField('姓名', validators=[DataRequired()])
    phone = StringField('电话')
    email = StringField('邮箱')
    company = StringField('公司', validators=[DataRequired()])
    frequency = SelectField('跟进频率',
                            choices=[('Weekly', '每周'), ('Monthly', '每月'), ('Quarterly', '每季度')])
    date = DateField('首次联系日期', validators=[DataRequired()])
    submit = SubmitField('创建记录')

模板优化(可选)

{% for field in form %}
    {% if field.type not in ['CSRFTokenField', 'SubmitField'] %}
        <div class="form-group mb-3">
            {{ field.label(class="form-label") }}
            {{ field(class="form-control") }}
            {% if field.errors %}
                {% for error in field.errors %}
                    <small class="text-danger d-block mt-1">{{ error }}</small>
                {% endfor %}
            {% endif %}
        </div>
    {% elif field.type == 'SubmitField' %}
        {{ field(class="btn btn-primary") }}
    {% endif %}
{% endfor %}

关键修改点

  1. 替换错误的request.post:POST请求时传入request.form,GET请求时无需传入表单数据,避免属性错误。
  2. 统一动态字段逻辑:将动态字段的创建代码移到请求判断之外,确保GET和POST请求的表单结构完全一致,防止验证失败。
  3. 通过表单对象获取数据:不再直接从request.form取值,而是使用表单对象的data属性,确保能获取到动态字段的输入值。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:18:29