简体   繁体   English

在 Flask / WTForms 中填充 select 字段更新上的文本字段

[英]Populate text fields on select field update in Flask / WTForms

Folks, scratching my head at this, there's a kind of an answer to this here , but having difficulty implementing it.伙计们,对此我感到头疼, 这里有一种答案,但难以实施。

I currently have a recipe and styles table, and when submit an "add recipe" form, it copies data from the styles table into the recipe.我目前有一个配方和 styles 表,当提交“添加配方”表单时,它会将 styles 表中的数据复制到配方中。 What I would like to do is to select a style in the add recipe form and have this data populate form fields.我想做的是添加配方表单中的 select 样式,并让这些数据填充表单字段。 So I'd like style-type for example to be populated in the form on updating the style select dropdown.因此,我希望例如在更新样式 select 下拉列表时填充样式类型。

My set up:我的设置:

Routes:路线:

@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')

Models:楷模:

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())

Forms: Forms:

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')

The Form HTML:表格 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>

My Javascript so far:到目前为止,我的 Javascript:

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

I can get some basic stuff working with the JS function.我可以使用 JS function 获得一些基本的东西。 So when I update the dropdown, it'll populate the field with some text.所以当我更新下拉列表时,它会用一些文本填充该字段。 What I can't figure out is how to pull the style_type info from the database.我想不通的是如何从数据库中提取 style_type 信息。 The link at the top here loads that info into the html tags of the text box, but it's a little different to what I'm doing.此处顶部的链接将该信息加载到文本框的 html 标记中,但这与我所做的有点不同。 The poster has looped through some items and it isn't a form.海报循环了一些项目,它不是一种形式。 My style_type_tag is just showing up as the raw text.我的style_type_tag只是显示为原始文本。 I'm guessing that the loop here is crucial but I can't quite make the step to getting into my setup.我猜这里的循环很关键,但我还不能完全进入我的设置。

Any help much appreciated!非常感谢任何帮助!

So the answer to this was building a simple API.所以这个问题的答案是构建一个简单的 API。 I'm sure there are simpler methods, but I wanted a bit of practice here and thought it would be useful in building other features into the project.我确信有更简单的方法,但我想在这里进行一些练习,并认为这对于在项目中构建其他功能很有用。

I followed Brad Traversy's vid on the subject and used the GET section to make this.我关注了 Brad Traversy 的关于该主题的视频,并使用 GET 部分进行了此操作。 His project was a simple single file project, so I had to get a bit more involved with imports etc in my project.他的项目是一个简单的单文件项目,所以我不得不在我的项目中更多地参与导入等。

  1. Grab postman to interact with the API抓住postman与 API 交互
  2. Install Marshmallow , To requirements.txt , add the lines:安装 Marshmallow ,到requirements.txt ,添加以下行:
flask-marshmallow
marshmallow-sqlalchemy

then run pip install -r requirements.txt然后运行pip install -r requirements.txt

  1. Import and initialise marshmallow.导入并初始化棉花糖。 In init.py:在 init.py 中:
from flask_marshmallow import Marshmallow
ma = Marshmallow(app)
  1. Add style schema To models.py将样式模式添加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)

Note that the strict=True isn't necessary any more with Marshmallow.请注意,对于 Marshmallow,不再需要strict=True

  1. Create endpoints/routes , to routes.py :创建 endpoints/routes ,到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. Update JS script :更新 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
      });
    });
}

Hope this helps anyone who runs into the same challenge!希望这可以帮助遇到同样挑战的任何人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM