Динамически обновлять SelectField на основе данных другого SelectField?

У меня небольшая проблема с этим. Вот обзор того, что я создал: простая форма с 2 полями выбора, 1 полем загрузки файла и кнопкой отправки. Первый выбор извлечет свои варианты из базы данных sql (у меня это закончилось). Затем, основываясь на том, что пользователь выбирает из SelectField1, SelectField2 будет заполнять его результатами из базы данных SQL. Я бы хотел, чтобы это произошло при выборе в номере 1. Другими словами, пусть selectfield2 динамически обновляет/заполняет себя без обновления страницы.

Рабочий процесс будет выглядеть примерно так:

  • Выберите имя клиента из SelectField1 (получите список планов клиентов, извлеченных из sql на основе выбора. Заполните SelectField2 ими, не обновляя страницу.)
  • Выберите один из планов клиентов в SelectField2.
  • Загрузите соответствующий pdf, используя
  • FileField
  • кнопка отправки

Может кто-то указать мне верное направление? Я работаю над этим дома на выходных, поэтому у меня нет подключения к базе данных. Я создал 3 списка для тестирования.

Я пытался сделать что-то вроде:

if form.sf_baclient.data == 'py':
    form.sf_clientplan.choices = list2
else:
    form.sf_clientplan.choices = list3

но это не сделало живое обновление. Вот код для html и представления:

HTML

    <form action="{{ url_for('index') }}" method=post>
        {{ form.hidden_tag() }}
        <dl>
            {{ form.sf_baclient.label }}<br>
            {{ form.sf_baclient }}<br>

            {{ form.sf_clientplan.label }}<br>
            {{ form.sf_clientplan }}<br>

            {{ form.ff_pdf_upload.label }}<br>
            {{ form.ff_pdf_upload }}<br>

        </dl>
        {{ form.sb_submit }}
    </form>

Вид

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

form = MyForm(request.form)

list1 = [('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')]
list2 = [('1', 'One'), ('2', 'Two'), ('3', 'Three')]
list3 = [('blue', 'Blue'), ('red', 'Red'), ('green', 'Green')]

form.sf_baclient.choices = list1
form.sf_baclient.choices.insert(0, ('', ''))

form.sf_clientplan.choices = list3
form.sf_clientplan.choices.insert(0, ('', ''))

if request.method == 'GET':
    return render_template('home.html', form=form)

elif request.method == 'POST':
    if form.sb_submit.data == True:
        message = form.sf_baclient.data
        # flash(message)

    return render_template('home.html', form=form, success=True)

person WTFox    schedule 17.05.2014    source источник
comment
тебе повезло с этим? Я должен сделать то же самое и не могу найти простого решения для этого.   -  person lucacerone    schedule 08.01.2015
comment
@lucacerone Только что опубликовал мой ответ. Посмотрите и дайте мне знать, если это поможет или нет.   -  person WTFox    schedule 10.01.2015


Ответы (2)


Большая часть этого должна быть написана на стороне клиента. Это то, что я в итоге сделал. Дайте мне знать, если это недостаточно ясно.

Создайте маршрут и URL-адрес в файле представлений для обработки. Обычно я начинаю их с подчеркивания и слова parse. Смотри ниже.

@app.route('/_parse_data', methods=['GET'])
def parse_data():
    if request.method == "GET":

        # only need the id we grabbed in my case. 
        id = request.args.get('b', 0)
        new_list = _call_to_db(id)

        # When returning data it has to be jsonify'ed and a list of tuples (id, value) to populate select fields.
        # Example: [('1', 'One'), ('2', 'Two'), ('3', 'Three')]

    return jsonify(new_list)

Вам нужно будет определить выбор, используя javascript/jquery. Итак, в моем javascript я написал это.

    $('#sf_baclient').on('change', function() {

            $("#sf_clientplan").empty();

            baclient_name = $("#sf_baclient option:selected").text();
            baclient_id = $("#sf_baclient option:selected").val();

            # Sending variables containing selection info to parse_data function in python.
            # jQuery's builtin ajax functions make things super easy 

            # Calling that parse url and sending it arguments
            $.getJSON($SCRIPT_ROOT + '/_parse_data', {
                a: baclient_name,
                b: baclient_id

            # Function to get data returned from parse_data and populate the second select field. 
            }, function(data) {
                # Using jQuery to populate new entries we got from flask.
                var options = $("#sf_clientplan");
                $.each(data, function() {
                    options.append($("<option />").val(this).text(this));
                });

            });
person WTFox    schedule 09.01.2015
comment
Фантастика, мне очень помогает. - person Josete Manu; 16.02.2020

if 'py' in form.sf_baclient.data:
    form.sf_clientplan.choices = list2
else:
    form.sf_clientplan.choices = list3

По логике он должен работать аналогично тому, что у вас есть. Я знаю, что ваша цель состоит в том, чтобы он обновлялся в реальном времени, попробуйте обернуть его в цикл while, что-то, что активируется, когда в form.sf_baclient.data есть данные.

person AutonomouSystem    schedule 17.05.2014
comment
ммм, наверное, чтобы получать обновления в реальном времени, нужно обновить страницу? В качестве альтернативы нужно сгенерировать небольшую функцию javascript (например, вот пример источника представления: alistapart.com /d/complexdynamiclists/dynamicselect.html) на основе фактического содержания? - person lucacerone; 10.01.2015