【问题标题】:How do I pre-fill a Flask WTForms Form with existing data for an "Edit Profile" route?如何使用“编辑配置文件”路由的现有数据预先填写 Flask WTForms 表单?
【发布时间】:2021-10-11 16:03:48
【问题描述】:

问题

每当我向属性form.[any-field-name].data写入数据时,写入的数据就会出现在表单中,这正是我想要的。但是,如果在呈现表单时对表单字段进行了更改,则新值似乎只存储在form.[any-field-name].raw_data 中。 form.[any-field-name].data 仅显示在用户有机会在字段中键入新值之前写入.data 的原始值。

显然我可以从.raw_data 获取结果,但这会破坏拥有表单验证库的目的。如何优雅地为用户预先填写表单字段,同时允许 Flask-WTForms 接受来自这些相同字段的新数据?

仅供参考:这与典型的“编辑个人资料”路线有点不同,因为每次编辑个人资料时,我的应用都会创建一个新的 UserVersion 记录。

Flask 路线

@app.route("/edit_user", methods=["GET", "POST"])
@login_required
def edit_user_self():
    """Edit user account that is currently logged in."""

    # get latest version of currently logged in user
    user_version = current_user.user_versions[0]

    # instantiate form and fill with existing data
    form = EditUserForm()
    form.username.data = user_version.username
    form.email.data = user_version.email
    form.addr_housenumber.data = user_version.addr_housenumber
    form.addr_street.data = user_version.addr_street
    form.addr_unit.data = user_version.addr_unit
    form.addr_city.data = user_version.addr_city
    form.addr_state.data = user_version.addr_state
    form.addr_postcode.data = user_version.addr_postcode

    if not form.validate_on_submit():
        return render_template("edit_user.html", form=form)
    else:
        # create new user version
        new_user_version = UserVersion(user=current_user,
            username = form.username.data,
            password = user_version.password,
            email = form.email.data,
            addr_housenumber = form.addr_housenumber.data,
            addr_street = form.addr_street.data,
            addr_unit = form.addr_unit.data,
            addr_city = form.addr_city.data,
            addr_state = form.addr_state.data,
            addr_postcode = form.addr_postcode.data
        )

        db.session.add(new_user_version)
        db.session.commit()

        flash("Changes saved")
        return redirect("/view_user")

表单模型

class EditUserForm(FlaskForm):
    username = StringField(
        "Username", validators=[DataRequired(message="Please enter a username")]
    )
    email = StringField(
        "Email",
        validators=[
            DataRequired(),
            Email(message="Please enter a valid email address"),
        ],
    )
    addr_housenumber = StringField("Housenumber", validators=[Length(max=80)])
    addr_housename = StringField("Housename", validators=[Length(max=80)])
    addr_conscriptionnumber = StringField(
        "Conscription Number", validators=[Length(max=80)]
    )
    addr_street = StringField("Street", validators=[Length(max=80)])
    addr_place = StringField("Place", validators=[Length(max=80)])
    addr_postcode = StringField("Postcode", validators=[Length(max=80)])
    addr_city = StringField("City", validators=[Length(max=80)])
    addr_country = StringField("Country", validators=[Length(max=80)])
    addr_hamlet = StringField("Hamlet", validators=[Length(max=80)])
    addr_suburb = StringField("Suburb", validators=[Length(max=80)])
    addr_subdistrict = StringField("Subdistrict", validators=[Length(max=80)])
    addr_province = StringField("Province", validators=[Length(max=80)])
    addr_state = StringField("State", validators=[Length(max=80)])
    addr_door = StringField("Door", validators=[Length(max=80)])
    addr_unit = StringField("Unit", validators=[Length(max=80)])
    addr_floor = StringField("Floor", validators=[Length(max=80)])
    addr_block = StringField("Block", validators=[Length(max=80)])
    submit = SubmitField("Save")

库版本

  • Flask 1.1.2
  • Flask WTForms 0.14.3
  • Flask SQLAlchemy 2.1

【问题讨论】:

    标签: python validation flask flask-sqlalchemy flask-wtforms


    【解决方案1】:

    你可以使用

    your_form = FormObject(obj=your_instance)
    # your_instance should have the same attributes that a FormObject has
    # data will be stored in the html <input> value attribute
    

    --------- 旧答案 我为此使用placeholder。您可以通过以下方式预先填写edit_user_self:

    form.username.render_kw({'placeholder':user_version.email})
    

    否则你可以像这样在 jinja 中做到这一点:

    {{wtf.form_field(form.email,
     placeholder=user_version.email)}}
    

    但要这样做,您应该将附加信息传递给 jinja 模板。

    【讨论】:

      【解决方案2】:

      你需要交换你的逻辑。测试表单提交并首先验证,否则预填充并返回表单:

      @app.route('/submit', methods=['GET', 'POST'])
      def submit():
          form = MyForm()
          
          if form.validate_on_submit():
              #Validate and Process submitted form first:
              new_user_version = UserVersion(user=current_user,
                                             username = form.username.data)
      
              db.session.add(new_user_version)
              db.session.commit()
              return redirect('/success')
      
          user_version = current_user.user_versions[0]
          #Pre-populate your form here:
          form.username.data = user_version.username
      
          return render_template('submit.html', form=form)
      

      【讨论】:

        猜你喜欢
        • 2016-06-23
        • 1970-01-01
        • 1970-01-01
        • 2013-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多