【问题标题】:Populate text fields on select field update in Flask / WTForms在 Flask / WTForms 中更新选择字段时填充文本字段
【发布时间】:2021-05-04 14:31:06
【问题描述】:

伙计们,对此我摸不着头脑,here 有一种答案,但难以实施。

我目前有一个食谱和样式表,当提交“添加食谱”表单时,它会将样式表中的数据复制到食谱中。我想做的是在添加配方表单中选择一种样式,并让这些数据填充表单字段。因此,我希望在更新样式选择下拉列表时将样式类型填充到表单中。

我的设置:

路线:

@app.route('/recipe/new', methods=['GET', 'POST'])
@login_required
def addrecipe():
    form = RecipeForm()
    if form.validate_on_submit():
        recipe = Recipe(recipe_name=form.recipe_name.data, 
                        recipe_style=form.style.data.id,
                        style_name=form.style.data.name, 
                        style_type = form.style.data.type)
        db.session.add(recipe)
        db.session.commit()
        flash('You added your recipe, get brewing!', 'success')
        return redirect(url_for('recipes'))
    return render_template('add_recipe.html', title = 'Add Recipe', form=form, legend='Add Recipe')

型号:

class Recipe(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    recipe_name = db.Column(db.String(100), nullable=False)
    recipe_style = db.Column(db.Text, db.ForeignKey('styles.id'))
    style_name = db.Column(db.String(100))
    style_type = db.Column(db.String(100))


# used for query_factory    
def getStyles():
    return Styles.query.order_by(Styles.name.asc())

表格:

class RecipeForm(FlaskForm):
    recipe_name = StringField('Recipe Name', validators=[DataRequired(), Length(min=2, max=20)])
    style = QuerySelectField(query_factory=getStyles, 
                            get_label="name")
    style_type = StringField('Style Type')

表单 HTML:

        <form method="POST" action="">
            {{ form.hidden_tag() }}
            <legend class="border-bottom mb-4">{{ legend }}</legend>
                <fieldset class="form-group card p-3 bg-light">
                    <h5 class="card-title">Overview</h5>
                    <div class="form-row">
                    <div class="form-group col-md-3">
                        {{ form.recipe_name.label(class="form-control-label") }}
                        {% if form.recipe_name.errors %}
                            {{ form.recipe_name(class="form-control form-control-sm is-invalid") }}
                            <div class="invalid-feedback">
                                {% for error in form.recipe_name.errors %}
                                    <span>{{ error }}</span>
                                {% endfor %}
                            </div>
                        {% else %}
                            {{ form.recipe_name(class="form-control form-control-sm") }}
                        {% endif %}
                    </div>
            </fieldset>
            <fieldset class="form-group card p-3 bg-light">
                <h5 class="card-title">Style</h5>
                <div class="form-row">
                    <div class="form-group col-md-3">
                        {{ form.style.label(class="form-control-label") }}
                        <input class="form-control form-control-sm" type="text" placeholder="Search Styles" id="myInput" onkeyup="filterFunction()">
                        {% if form.style.errors %}
                            {{ form.style(class="form-control form-control-sm is-invalid") }}
                            <div class="invalid-feedback">
                                {% for error in form.style.errors %}
                                    <span>{{ error }}</span>
                                {% endfor %}
                            </div>
                        {% else %}
                            {{ form.style(class="form-control form-control-sm", id="style_name") }}
                        {% endif %}
                    </div>
                    <div class="form-group col-md-2">
                        {{ form.style_type.label(class="form-control-label") }}
                        {% if form.style_type.errors %}
                            {{ form.style_type(class="form-control form-control-sm is-invalid") }}
                            <div class="invalid-feedback">
                                {% for error in form.style_type.errors %}
                                    <span>{{ error }}</span>
                                {% endfor %}
                            </div>
                        {% else %}
                            {{ form.style_type(class="form-control form-control-sm", id="styletype", style_type_tag='{{ form.style.data.type }}' ) }}
                        {% endif %}
                    </div>
            </div>
            </fieldset>

到目前为止我的 Javascript:

style_name.oninput = function(o) {
    // style = document.getElementById('styletype')
    styletype.value = $(o).attr('style_type_tag')
    }

我可以使用 JS 函数获得一些基本的东西。所以当我更新下拉列表时,它会用一些文本填充该字段。我想不通的是如何从数据库中提取 style_type 信息。此处顶部的链接将该信息加载到文本框的 html 标记中,但这与我正在做的有点不同。海报循环了一些项目,它不是一种形式。我的 style_type_tag 只是显示为原始文本。我猜这里的循环很关键,但我还不能完全进入我的设置。

非常感谢任何帮助!

【问题讨论】:

    标签: javascript flask wtforms


    【解决方案1】:

    所以这个问题的答案是构建一个简单的 API。我确信有更简单的方法,但我想在这里进行一些练习,并认为这对于将其他功能构建到项目中会很有用。

    我关注了 Brad Traversy 的 vid 并使用 GET 部分进行了此操作。他的项目是一个简单的单文件项目,所以我不得不在我的项目中更多地参与导入等。

    1. 获取 postman 与 API 交互
    2. 安装 Marshmallow,在 requirements.txt 中添加以下行:
    flask-marshmallow
    marshmallow-sqlalchemy
    

    然后运行 pip install -r requirements.txt

    1. 导入并初始化棉花糖。 在 init.py 中:
    from flask_marshmallow import Marshmallow
    ma = Marshmallow(app)
    
    1. 添加样式架构models.py
    # import module
    from flaskblog import ma
    
    # create schema with the fields required
    class StyleSchema(ma.Schema):
        class Meta:
            fields = ("id", "name", "origin", "type")
    
    # initialise single style schema
    style_schema = StyleSchema()
    # initialise multiple style schema
    styles_schema = StyleSchema(many=True)
    

    请注意,棉花糖不再需要 strict=True

    1. 创建端点/路由routes.py
    # Get All Styles
    
    @app.route('/styleget', methods=['GET'])
    def styles_get():
        all_styles = Styles.query.all()
        result = styles_schema.dump(all_styles)
        # return jsonify(result.data) - note that this line is different to the video, was mentioned in the comments. Was originally "return jsonify(result.data)"
        return styles_schema.jsonify(all_styles)
    
    # Get Single Product
    
    # passes the id into the URL
    @app.route('/styleget/<id>', methods=['GET'])
    def style_get(id):
        style = Styles.query.get(id)
        return style_schema.jsonify(style)
    
    1. 更新 JS 脚本
    style_name.onchange = function() {
            // creates a variable from the dropdown
        style = document.getElementById('style_name').value
            // uses the variable to call the API and populate the other form fields
        fetch('/styleget/' + style).then(function(response) {
          response.json().then(function(data) {
            // this takes the 'type' data from the JSON and adds it to the styleType variable
            styleType = data.type;
            // adds the data from the variable to the form field using the ID of the form. 
            styletype.value = styleType
          });
        });
    }
    

    希望这对遇到同样挑战的人有所帮助!

    【讨论】:

      猜你喜欢
      • 2017-05-05
      • 2021-07-09
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      相关资源
      最近更新 更多