简体   繁体   中英

Python Flask dynamic choices SelectField

I got the dynamic selectfield finally working which shows the subcategories for that one category you choose. The only problem now is that whenever I want to store the entry and submit, it just reloads the page and resets the subcategories and won't let me store the new entry.

This is the tutorial I followed:

app.py

from flask import Flask, render_template, request, jsonify
from flask_sqlalchemy import SQLAlchemy 
from flask_wtf import FlaskForm 
from wtforms import SelectField

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SECRET_KEY'] = 'secret'

db = SQLAlchemy(app)

class City(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    state = db.Column(db.String(2))
    name = db.Column(db.String(50))

class Form(FlaskForm):
    state = SelectField('state', choices=[('CA', 'California'), ('NV', 'Nevada')]) 
    city = SelectField('city', choices=[])

@app.route('/', methods=['GET', 'POST'])
def index():
    form = Form()
    form.city.choices = [(city.id, city.name) for city in City.query.filter_by(state='CA').all()]

    if request.method == 'POST':
        city = City.query.filter_by(id=form.city.data).first()
        return '<h1>State: {}, City: {}</h1>'.format(form.state.data, city.name)

    return render_template('index.html', form=form)

@app.route('/city/<state>')
def city(state):
    cities = City.query.filter_by(state=state).all()

    cityArray = []

    for city in cities:
        cityObj = {}
        cityObj['id'] = city.id
        cityObj['name'] = city.name
        cityArray.append(cityObj)

    return jsonify({'cities' : cityArray})

if __name__ == '__main__':
    app.run(debug=True)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <form method="POST">
    {{ form.csrf_token }}
    {{ form.state }}
    {{ form.city }}
    <input type="submit">
    </form>
    <script>
        var state_select = document.getElementById("state");
        var city_select = document.getElementById("city");

        state_select.onchange = function()  {
             
            state = state_select.value;
            
            fetch('/city/' + state).then(function(response) {

                response.json().then(function(data) {
                    var optionHTML = '';

                    for (var city of data.cities) {
                        optionHTML += '<option value="' + city.id + '">' + city.name + '</option>';
                    }

                    city_select.innerHTML = optionHTML;
                })
                
            });
        }
    </script>
</body>
</html>

This is how my code looks:

@app.route("/data/create", methods=["GET", "POST"])
def create():
    form = NewEntry()

    if form.validate_on_submit():
        form.Unterkategorie.choices = [
            (Unterkategorie.Name, Unterkategorie.Name)
            for Unterkategorie in Unterkg.query.filter_by(
                Kategorie="01_GENERAL_REQUIREMENTS"
            ).all()
        ]
        
        employee = WissenModel(
            
            Kategorie=form.Kategorie.data,
            Unterkategorie=form.Unterkategorie.data,
            
        )
        db.session.add(employee)
        db.session.commit()
        flash(f"Eintrag hinzugefügt!", "success")
        return redirect(url_for("RetrieveList"))
    return render_template("createpage.html", form=form, title="New Entry")

@app.route("/Unterkategorie/<Kategorie>")
def Unterkategorie(Kategorie):
    Unterkategorien = Unterkg.query.filter_by(Kategorie=Kategorie).all()

    UnterkategorieArray = []

    for Unterkategorie in Unterkategorien:
        UnterkategorieObj = {}
        UnterkategorieObj["id"] = Unterkategorie.id
        UnterkategorieObj["Name"] = Unterkategorie.Name
        UnterkategorieArray.append(UnterkategorieObj)
    return jsonify({"Unterkategorien": UnterkategorieArray})

My code is lacking this part:

if request.method == 'POST':
        city = City.query.filter_by(id=form.city.data).first()

But when I have if form.validate_on_submit(): I shouldn't need the if request.method == 'POST': right?

Try with form.is_submitted(), then save form.name. Maybe this can help.

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.

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