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. What I would like to do is to select a style in the add recipe form and have this data populate form fields. So I'd like style-type for example to be populated in the form on updating the style select dropdown.
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:
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:
<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:
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. 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. 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. 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. 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. 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. His project was a simple single file project, so I had to get a bit more involved with imports etc in my project.
flask-marshmallow
marshmallow-sqlalchemy
then run pip install -r requirements.txt
from flask_marshmallow import Marshmallow
ma = Marshmallow(app)
# 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.
# 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)
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!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.