在 Flask-WTF 中填充表单和选择默认值

Populating forms and selecting defaults in Flask-WTF

我有一个用于撰写和编辑博客 post 的表单,如下所示:

class EditorForm(FlaskForm):
    title = StringField('Title', validators=[DataRequired(), Length(min=1, max=250)])
    body = PageDownField('Body', validators=[DataRequired()])
    tags = SelectMultipleField('Tags', coerce=int)
    timestamp = DateTimeField('Timestamp')
    published = BooleanField('Publish?')
    update = BooleanField('Update Timestamp?')
    delete = SubmitField('Delete')
    submit = SubmitField('Save')

在我看来,我区分编辑现有 post 和创建新的。对于现有的 post,如果它们有关联的标签,我希望它们在表单的 SelectMultipleField 中突出显示,以便用户可以看到它们。

如果这些被突出显示并且我想删除标签,我需要能够取消突出显示并提交表单来执行此操作。

以下是我目前观点的相关部分:

@app.route('/editor/<slug>', methods=['GET', 'POST'])
@app.route('/editor/', methods=['GET', 'POST'])
@login_required
def editor(slug=None):
    # old post or new post?
    if slug:
        post = Post.query.filter_by(slug=slug).first()
    else:
        post = Post()

    # populate form, blank for new post
    form = EditorForm(obj=post)
    
    # populate tags field
    form.tags.choices = [(tag.id, tag.tag) for tag in Tag.query.order_by('tag')]

    # declare list for tag highlights on GET
    if request.method == 'GET':
        form.tags.default = []

    # if post has linked tags, highlight them
    if post.tags:
        for tag in post.tags:
            if tag.id not in form.tags.default:
                form.tags.default.append(tag.id)
        form.process()

在寻找与我的问题相关的 other questions 时,我发现我不能直接使用 form.tags.data 来突出显示关联的标签,因为这意味着该字段忽略了用户在表单上的操作,即使正确的选择会突出显示。这就是我使用 form.tags.default.

的原因

form.tags.default 似乎可以突出显示正确的标签,但 form.process() 会擦除由 form = EditorForm(obj=post).

填写的所有其他字段

所以我的问题是:如何使用现有 post 数据填充我的表单并在同一实例中突出显示正确的标签?

这个问题我好像得到了我想要的结果。我原来的部分问题实际上与我在问题中没有 post 的一些代码有关。

if form.validate_on_submit():,我将 form.tags.data 中的标签(突出显示的选项)附加到我的 post.tags。 在 post 已经附加标签的情况下,这意味着取消选择字段中的默认值确实会根据需要清空 form.tags.data,但是 post.tags 仍然有原始数据,因此没有变化。

已通过以下方式解决:

# empty tags list then add highlighted choices
    post.tags = []
    for id in form.tags.data:
        t = Tag.query.filter_by(id=id).first()
        post.tags.append(t)

我还更改了填充表单的代码,使其更简单。我错了需要使用 default 而不是 data(坦率地说,我不明白两者之间的区别):

    # populate form, blank for new post
    form = EditorForm(obj=post)
    # populate tags field
    form.tags.choices = [(tag.id, tag.tag) for tag in Tag.query.order_by('tag')]
    # populate defaults only on GET otherwise user choice overidden
    if request.method == 'GET':
        # declare default (highlighted) tags list
        form.tags.data = []
        # if post has tags, highlight them
        if post.tags:
            for tag in post.tags:
                form.tags.data.append(tag.id)