我目前正在使用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将根据上一个selectfield提取数据。
例如,用户在Country中选择Australia,那么State的第二个selectfield应该只包含Australia中的states。
我对这个问题做了一些研究,但没有一个令人满意的解决方案。以下是我发现的两个可能但不令人满意的解决方案。
1.使用jQuery插件,例如Chained。但是,这个插件需要逐行编码。如果我采用这种方法,至少还会有400多条线,这不是很蟒蛇。例如:
<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的默认值提取一次数据。例如:如果country的默认selectfield是Australia,那么state selectfield将只包含Australia内的states。当您将country selectfield改为America时,state selectfield仍然只包含澳大利亚境内的州。以下是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')]
从上面的研究中,我假设令人满意的解决方案应该介于两者之间,并且它肯定应该包含一些Javascript来监视客户端活动,而不向服务器发送请求。有没有人有一个令人满意的解决方案的烧瓶框架?
最佳答案
如果你想在客户端上有动态的东西,就没办法写一些JavaScript。幸运的是这不是你估计的400多行。本例不使用WTForms,但这并不重要。关键部分是将可用选项作为JSON发送,并动态更改可用选项。这里有一个单文件可运行烧瓶应用程序,演示了基本思想。
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()