1

I'm trying to retrieve the selected option on a dynamic dependent dropdown list, but I only get None using request.form.get. My example generates a dropdown list in the image below:

enter image description here

The full code to generate the dropdown list is below, and it is based on an answer to this question.

from flask import Flask, render_template_string, request, redirect

app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def index():

    systems = {
        'PlayStation': {'Spyro': ['1', '2', '3'], 'Crash': ['4', '5', '6'], 'Ico': ['7', '8']},
        'N64': {'Mario Kart': ['Mario', 'Luigi'], 'Superman': ['12', '13', '14']}
    }
    
    if request.method == "POST":

        systemGet = request.form.get("system")
        gameGet = request.form.get("game")
        charactersGet = request.form.get("characters")
        
        print(systemGet)
        print(gameGet)
        print(charactersGet)

        return redirect('temp.html')

    return render_template_string(template, systems=systems)
    
    

template = """
<!doctype html>
<form method="POST">
    <select id="system">
        <option></option>
    </select>
    <select id="game"></select>
    <select id="characters"></select>
    <button type="submit">Play</button>
</form>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
    "use strict";

    var systems = {{ systems|tojson }};

    var form = $('form');
    var system = $('select#system');
    var game = $('select#game');
    var characters = $('select#characters');

    for (var key in systems) {
        system.append($('<option/>', {'value': key, 'text': key}));
    }

    system.change(function(ev) {
        game.empty();
        game.append($('<option/>'));

        var games = systems[system.val()];

        for (var i in games) {
            game.append($('<option/>', {'value': i, 'text': i}));
        }
    });
    
    game.change(function(evV) {
        characters.empty();
        characters.append($('<option/>'));

        var games = systems[system.val()][game.val()];

        for (var i in games) {
            characters.append($('<option/>', {'value': games[i], 'text': games[i]}));
        }
    });

</script>
"""

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

Edit: Including the name attribute, as proposed by @vremes, all works. The solution becomes:

from flask import Flask, render_template_string, request, redirect

app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def index():

    systems = {
        'PlayStation': {'Spyro': ['1', '2', '3'], 'Crash': ['4', '5', '6'], 'Ico': ['7', '8']},
        'N64': {'Mario Kart': ['Mario', 'Luigi'], 'Superman': ['12', '13', '14']}
    }
    
    if request.method == "POST":

        systemGet = request.form.get("system")
        gameGet = request.form.get("game")
        charactersGet = request.form.get("characters")
        
        print(systemGet)
        print(gameGet)
        print(charactersGet)

        return redirect('temp.html')

    return render_template_string(template, systems=systems)
    
    

template = """
<!doctype html>
<form method="POST">
    <select id="system" name="system">
    </select>
    
    <select id="game" name="game">
    </select>
    
    <select id="characters" name="characters">
    </select>
        
    <button type="submit">Play</button>
</form>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
    "use strict";

    var systems = {{ systems|tojson }};

    var form = $('form');
    var system = $('select#system');
    var game = $('select#game');
    var characters = $('select#characters');

    for (var key in systems) {
        system.append($('<option/>', {'value': key, 'text': key}));
    }

    system.change(function(ev) {
        game.empty();
        game.append($('<option/>'));

        var games = systems[system.val()];

        for (var i in games) {
            game.append($('<option/>', {'value': i, 'text': i}));
        }
    });
    
    game.change(function(evV) {
        characters.empty();
        characters.append($('<option/>'));

        var games = systems[system.val()][game.val()];

        for (var i in games) {
            characters.append($('<option/>', {'value': games[i], 'text': games[i]}));
        }
    });

</script>
"""

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

1 Answer 1

1

request.form.get relies on HTML name attribute, add name attribute to each of your select dropdowns, for example:

<!-- request.form.get('system') should work now -->
<select id="system" name="system">
    <option value="mario">Mario</option>
</select>
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you, @vremes. Now I have a correct result using request.form.get, but got a new error. I edited the original question to show what the problem is.
I copied/pasted your code and tested it, i'm unable to reproduce your issue, i selected N64 -> Mario Kart, only Mario and Luigi options are shown on my end, i'm using Firefox.
I suppose the problem is because I'm including all 'characters'/'games' as 'option', but only the 'characters' for each 'game' should be present. Including the delimited 'options' is actually done by the function 'game.change(function(evV)', whenever I decide for a game. So, the code works fine just including 'name="system"', and without including any 'option'. The 'option' inclusion should be handled by the functions.
I accepted your answer because you mentioned the 'name' attribute. Thank you very much! I edited my question to include the complete fixed code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.