Flask+WTForms,动态生成的字段列表

2024-05-03 12:09:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在制作一个烧瓶应用程序,基本上是基于形式的,所以我使用WTForms和烧瓶wtf。

我目前正在重构我的代码,因此我的整个表单使用WTForms,其中有一个非常动态的部分我无法使用WTForms实现。我不知道怎么做,我最初的想法不起作用,我找不到关于我的问题的参考资料或教程,所以这就是我寻求帮助的原因。

因此,该表单允许用户提交包含以下内容的对象:

  • 标签(StringField,easy)
  • 一个描述(TextAreaField,也很简单;尽管我很难使默认值工作)
  • 形式的属性列表(谓词、对象),其中谓词取自预先构建的列表,对象基本上可以是任何对象,但每个谓词都将生成特定对象(例如,谓词“related to”将期望另一个对象(来自下拉列表),谓词“resource”将期望http链接某种程度上)。此列表可以为空。

你可以猜到我对名单有意见。现在代码的工作方式是,我使用wtforms获取标签和描述,属性列表是使用一个config常量(在整个代码中使用,所以如果我想添加新属性,我只有一个地方可以编辑)和javascript中的一个动态菜单来创建(这里,用于谓词)字段,然后我可以在view函数中使用flask.request.form对象。谓词的所有隐藏字段都具有相同的name属性,对象的所有隐藏字段都具有相同的name属性。

以下是表单视图的外观,由几个属性初始化:

http://i.imgur.com/bfMG95s.png

在“Propriétés”标签下,您有一个下拉列表来选择谓词,第二个字段根据所选谓词显示或隐藏(可以是下拉列表或文本字段),只有当您单击“ajuter Propriété”(“添加属性”)时,才会在下面的选项卡中添加新行并生成字段。

我不想改变这方面的任何东西,因为它的工作非常好,使形式非常直观,基本上正是我希望它是从用户端。

这就是我的自定义表单现在的样子(它不起作用,无论我提交表单的字段数是多少,属性都保持为空):

class PropertyForm(Form):
    property_predicate = HiddenField(
        validators=[AnyOf(values=app.config["PROPERTY_LIST"].keys())]
    )
    property_object = HiddenField(
        validators=[DataRequired()]
    )

class CategoryForm(Form):
    """
        Custom form class for creating a category with the absolute minimal
        attributes (label and description)
    """
    label = StringField(
        "Nom de la categorie (obligatoire)",
        validators=[DataRequired()]
    )
    description = TextAreaField(
        "Description de la categorie (obligatoire)",
        validators=[DataRequired()]
    )
    properties = FieldList(FormField(PropertyForm),validators=[Optional()])

下面是我想在views.py代码(我目前正在重构)中做的事情:

def cat_editor():
    cat_form = CategoryForm()
    if request.method == "GET":
        # Do GET stuff and display the form
        return render_template("cateditor.html", form=cat_form, varlist=template_var_list)
    else if request.method == "POST":
        if cat_form.validate_on_submit():
            # Get values from form
            category_label = cat_form.label.data
            category_description = cat_form.description.data
            category_properties = cat_form.properties.data
            # Do POST stuff and compute things
            return redirect(url_for("index"))
        else:
            # form didn't validate so we return the form so the template can display the errors
            return render_template("cateditor.html", form=cat_form,
                                    template_var_list = template_var_list)

基本结构工作得很好,只是那个该死的动态列表,我不能正常工作。

从WTForms CategoryForm实例获取标签和描述工作正常,但属性始终返回空列表。理想情况下,我希望能够得到一个表单列表[(predicte1,property1),(predicte2,object2)。。。]调用cat_form.properties.data时(这就是为什么我有一个表单字段列表,每个字段中有两个HiddenField),但是只要使用WTForms,就不必从两个列表构建这样的列表。知道吗?非常感谢:)


Tags: the对象代码form表单列表属性template
2条回答

使用jQuery获取表单中更动态的元素/行为。请注意,表单字段有一个隐藏属性(或方法,具体取决于是否使用bootstrap),允许您呈现可能需要的所有内容,但仅在需要时显示字段,否则隐藏它们。动态添加字段有点困难,但并非完全不可能。与属性关联的字段数是否有限制?如果是的话,我只会渲染最大数量的字段(只要合理,最多5个似乎没问题,当您达到用户可以添加的最大属性数的两位数时,渲染一堆您永远不会使用的字段会变得不雅)。

Here's这是一个很好的地方,可以看看它是如何工作的。当然,您还有一个选择何时隐藏或显示相关字段的问题,但是也可以通过使用jQuery的.change()事件的javascript/jQuery脚本来处理。像这样的:

$("#dropdown").change(function () {
    var chosen_val = $(this).val();
    if (chosen_val == 'banana'){$('#property1').show();} else {$('#property1').hide();}
   });

这段代码可能会工作,而且肯定缺乏正确的逻辑,但是应该能让您了解如何使用jQuery解决这个问题。请注意,“property1”字段始终存在,等待用户选择正确的下拉值时显示。

我通过使用FieldList对象和append_entry()来发现问题所在,看看如果我要生成一个预填充的属性列表,wtf将生成什么样的HTML代码。

我的Javascript生成了所有同名的隐藏字段,据我所知,WTForms能够聚合同名的字段来创建列表。问题是,那些同名字段是嵌套在FieldList对象名属性中的FormField本身的一部分。

为了让WTForms Form对象区分一组隐藏字段,在FieldList中嵌套Form fields时,它会在FormFields字段名前面加上“FieldList_name-index-”。这意味着WTForms所期望的是

<input type="hidden", name="properties-0-property_predicate" value=...>
<input type="hidden", name="properties-0-property_object" value=...>

<input type="hidden", name="properties-1-property_predicate" value=...>
<input type="hidden", name="properties-1-property_object" value=...>

<input type="hidden", name="properties-2-property_predicate" value=...>
<input type="hidden", name="properties-2-property_object" value=...>

我修改了javascript,以便它生成适当的名称。现在,当我调用cat_form.properties.data时,我得到了如下信息:

[{"property_predicate": "comment", "property_object":"bleh"},
 {"property_predicate": "comment", "property_object": "bleh2"}]

这正是我需要的。出于某种原因,表单没有验证,但至少我知道如何使WTForms提取数据,我的javascript生成的隐藏字段,这就是问题所在。

编辑:表单验证之所以发生,是因为必须将CSRF隐藏输入与CSRF一起插入到使用FormField生成的每个子表单中。

相关问题 更多 >