小编典典

如何在不刷新页面的情况下在Flask中创建链接的selectfield?

python

我目前正在使用wtf处理地址表格,其中包含国家/地区,州/省,城市等。数据库全部用FK设置。

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'))

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

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

我已经对该主题进行了一些研究,但无法提出令人满意的解决方案。这是我发现的两个可能但又不容忽视的解决方案。

1.使用jQuery插件,例如链式。但是,此插件需要逐行编码。如果我采用这种解决方案,那么至少还会有400多行代码,而这并不是很pythonic。例如:

<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的“具有动态选择值的选择字段”,这也是不希望的,因为它仅根据以前选择字段的默认值提取一次数据。例如:如果国家/地区的默认选择字段是澳大利亚,则州选择字段将仅包含澳大利亚内的州。当您将国家/地区选择字段更改为“美国”时,州/地区选择字段仍将仅包含澳大利亚内的州。以下是wtf文档中列出的有关此方法的教程:

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')]

根据以上研究,我认为令人满意的解决方案应该介于两者之间,并且肯定应该包含一些Java脚本来监视客户端活动,而不向服务器发送请求。有人对Flask框架有令人满意的解决方案吗?


阅读 211

收藏
2020-12-20

共1个答案

小编典典

如果您希望客户端动态处理某些内容,则无法编写一些JavaScript。幸运的是,这不是您估计的400多条线。此示例未使用WTForms,但这并不是很重要。关键部分是将可用选项作为JSON发送,并动态更改可用选项。这是一个可运行的单文件Flask应用程序,演示了基本思想。

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 = """



<!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>



"""

app.run()
2020-12-20