首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在flask中创建链接的selectfield而不刷新页面?

如何在flask中创建链接的selectfield而不刷新页面?
EN

Stack Overflow用户
提问于 2014-09-23 00:31:00
回答 2查看 9.9K关注 0票数 3

我目前正在使用wtf编写一个地址表单,其中包含国家、州和City..etc。数据库已经用FK设置好了。

代码语言:javascript
复制
class Country(db.Model):
    __tablename__ = 'countries'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    users = db.relationship('User', backref='countries', lazy='dynamic')
class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    countries_id = db.Column(db.Integer, db.ForeignKey('countries.id')) 

现在我正在尝试实现一种链式选择字段排序效果,以优化用户体验。期望的效果是无需离开或刷新页面即可使选择字段根据先前的选择字段拉取数据。

例如,用户在国家中选择澳大利亚,那么第二个州的选择字段应该只包含澳大利亚的州。

我在这个问题上做了一些研究,但没有想出一个令人满意的解决方案。以下是我找到的两种可能但不令人满意的解决方案。

1.使用jQuery-plugin,例如链式。但是,这个插件需要逐行编码。如果我采用这个解决方案,至少会有另一条400+行,这并不是很严格。例如:

代码语言:javascript
复制
<select id="series" name="series">
  <option value="">--</option>
  <option value="series-3" class="bmw">3 series</option>
  <option value="series-5" class="bmw">5 series</option>
  <option value="series-6" class="bmw">6 series</option>
  <option value="a3" class="audi">A3</option>
  <option value="a4" class="audi">A4</option>
  <option value="a5" class="audi">A5</option>
</select>

2.使用Wtf的“使用动态选择值选择字段”,这也是不可取的,因为它只提取一次数据,这取决于前一个selectfield的默认值。例如:如果国家的默认选择字段是澳大利亚,则州选择字段将仅包含澳大利亚境内的州。当您将“国家”选择字段更改为“美国”时,州选择字段仍然只包含澳大利亚境内的州。下面是wtf文档中列出的此方法的教程:

代码语言:javascript
复制
class UserDetails(Form):
    group_id = SelectField(u'Group', coerce=int)

def edit_user(request, id):
    user = User.query.get(id)
    form = UserDetails(request.POST, obj=user)
    form.group_id.choices = [(g.id, g.name) for g in Group.query.order_by('name')]

从上面的研究中,我假设令人满意的解决方案应该介于两者之间,并且肯定应该使用一些Javascript来监控客户端活动,而不需要向服务器发送请求。有没有人对flask框架有一个令人满意的解决方案?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-23 12:56:21

如果你想在客户机上有动态的东西,那就没有办法写一些JavaScript了。幸运的是,这不是您估计的400+行。本例没有使用WTForms,但这并不重要。关键部分是以JSON格式发送可用选项,并动态更改可用选项。这里有一个单文件可运行的Flask应用程序,它演示了基本思想。

代码语言:javascript
复制
from flask import Flask, render_template_string

app = Flask(__name__)

@app.route('/')
def index():
    systems = {
        'PlayStation': ['Spyro', 'Crash', 'Ico'],
        'N64': ['Mario', 'Superman']
    }

    return render_template_string(template, systems=systems)

template = """
代码语言:javascript
复制
<!doctype html>
<form>
    <select id="system">
        <option></option>
    </select>
    <select id="game"></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');

    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': games[i], 'text': games[i]}));
        }
    });

    form.submit(function(ev) {
        ev.preventDefault();
        alert("playing " + game.val() + " on " + system.val());
    });
</script>
代码语言:javascript
复制
"""

app.run()
票数 15
EN

Stack Overflow用户

发布于 2018-04-23 03:05:37

我最近遇到了一个类似的问题,并使用this answer的想法解决了它。

最小的示例可能如下所示:

因此,只有两个下拉框,第二个依赖于第一个下拉框的选定值;页面上的所有其他元素都不受此选择的影响(这里我只使用一个复选框)。一旦做出选择,下拉菜单下面的按钮将触发一个操作,然后结果可以再次显示在页面上(在这里,我只更新按钮下面的句子,当然你也可以做更合理的事情),例如:

HTML文件如下所示(位于templates/index.html中):

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
  <head>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-center text-muted">Dynamic dropdowns</h3>
      </div>

      <div>
        Check me and I don't change status when you select something below
      </div><br>
      <div>
        <input class="form-check-input" type="checkbox" value="" id="use_me">Select me
      </div><br><br>

      <div class="row">
        <div class="form-group col-xs-6">
          <label for="all_classes">Select a class</label>
          <select class="form-control" id="all_classes">
            {% for o in all_classes %}
                    <option value="{{ o }}">{{ o }}</option>
            {% endfor %}
          </select>
        </div>
        <div class="form-group col-xs-6">
          <label for="all_entries">Select an entry</label>
          <select class="form-control" id="all_entries">
            {% for o in all_entries %}
                    <option value="{{ o }}">{{ o }}</option>
            {% endfor %}
          </select>
        </div>
      </div>

      <div>
        <button type="button" id="process_input">Process selection!</button>
      </div><br><br>
      <div id="processed_results">
        Here we display some output based on the selection
      </div>
    </div>
    <script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function() {

        $('#all_classes').change(function(){

          $.getJSON('/_update_dropdown', {
            selected_class: $('#all_classes').val()

          }).success(function(data) {
                $('#all_entries').html(data.html_string_selected);
           })
        });
        $('#process_input').bind('click', function() {

            $.getJSON('/_process_data', {
                selected_class: $('#all_classes').val(),
                selected_entry: $('#all_entries').val(),


            }).success(function(data) {
                $('#processed_results').text(data.random_text);
            })
          return false;

        });
      });
    </script>
  </body>
</html>

相应的python脚本如下所示:

代码语言:javascript
复制
from flask import Flask, render_template, request, jsonify
import json

# Initialize the Flask application
app = Flask(__name__)


def get_dropdown_values():

    """
    dummy function, replace with e.g. database call. If data not change, this function is not needed but dictionary
    could be defined globally
    """

    class_entry_relations = {'class1': ['val1', 'val2'],
                             'class2': ['foo', 'bar', 'xyz']}

    return class_entry_relations


@app.route('/_update_dropdown')
def update_dropdown():

    # the value of the first dropdown (selected by the user)
    selected_class = request.args.get('selected_class', type=str)

    # get values for the second dropdown
    updated_values = get_dropdown_values()[selected_class]

    # create the value sin the dropdown as a html string
    html_string_selected = ''
    for entry in updated_values:
        html_string_selected += '<option value="{}">{}</option>'.format(entry, entry)

    return jsonify(html_string_selected=html_string_selected)


@app.route('/_process_data')
def process_data():
    selected_class = request.args.get('selected_class', type=str)
    selected_entry = request.args.get('selected_entry', type=str)

    # process the two selected values here and return the response; here we just create a dummy string

    return jsonify(random_text="you selected {} and {}".format(selected_class, selected_entry))


@app.route('/')
def index():

    """
    Initialize the dropdown menues
    """

    class_entry_relations = get_dropdown_values()

    default_classes = sorted(class_entry_relations.keys())
    default_values = class_entry_relations[default_classes[0]]

    return render_template('index.html',
                           all_classes=default_classes,
                           all_entries=default_values)


if __name__ == '__main__':

    app.run(debug=True)
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25978879

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档