如何使用 Python、Flask 和 SQLite3 实现下拉 select 选项的动态依赖更改?
How do I implement dynamic dependent change of dropdown select options, using Python, Flask and SQLite3?
美好的一天。我真的是编程新手(3 个月),我正在尝试为我的课程期末项目添加最后一个功能。
在我的 html 页面中,我有 5 个 select 容器,第一个容器的数据来自我的 app.py 中的元组对象,其余 4 个选项数据来自 sqlite3 数据库查询。我希望这些选项相互依赖,无论用户首先 select 编辑哪个选项。
为了让您更多地了解我在说什么,所有选项都与武器类型相关(这是一个用于管理在线游戏库存的网络应用程序),此“类型”列存在于每个 table用于查询,远程武器表示为“1”,近战武器表示为“2”,两种类型均表示为“0”。
所以我是怎么理解的,我需要在一个选项被 selected 之后发出一个 json 请求,并且 return 将新的查询结果返回给 html 以便使用 javascript 处理新数据?但是接下来,当新选项将 selected 并减少变体时......我完全迷失在这里,因为我的 javascript 经验仅与 bootstrap (copy/paste )...
我希望我清楚地解释了一切,并且非常感谢一些如何做的例子。谢谢你的时间。
我的python代码:
@app.route("/add", methods=["GET", "POST"])
@login_required
def add():
# assigning user_id to session
user_id = session["user_id"]
# this will be used for future dynamic change feature
weapon_type = ("-1", "1")
if request.method == "POST":
# assigning user's input
wtype = request.form.get("wtype")
wname = request.form.get("wname")
main_p = request.form.get("main_p")
major_p = request.form.get("major_p")
minor_p = request.form.get("minor_p")
# check if input fields are blank or not valid
if not wtype or wtype not in weapon_type:
return apology("Invalid type")
if not wname:
return apology("Invalid type")
if not main_p:
return apology("Invalid type")
# adding new weapon into users_weapons table
db.execute("INSERT INTO user_weapons (user_id, weapon_id, main_id, major_id, minor_id) VALUES(?, ?, ?, ?, ?)", user_id, wname, main_p, major_p, minor_p)
return redirect("/inventory")
else:
# adding options for select forms
weapons = db.execute("SELECT id, name FROM weapons")
mains = db.execute("SELECT id, name FROM mainp")
majors = db.execute("SELECT id, description FROM majorp")
minors = db.execute("SELECT id, description FROM minorp")
return render_template("add.html", weapons=weapons, mains=mains, majors=majors, minors=minors)
我的html代码:
{% block main %}
<form action="/add" method="post">
<div class="form-group">
<select class="form-control col-md-4 bg-dark text-success" name="wtype">
<option disabled selected>Weapon Type</option>
<option value="-1">Melee</option>
<option value="1">Ranged</option>
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="wname">
<option disabled selected>Weapon Name</option>
{% for weapon in weapons %}
<option value="{{ weapon["id"] }}"> {{ weapon["name"] }} </option>
{% endfor %}
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="main_p">
<option disabled selected>Main Prefix *</option>
{% for main in mains %}
<option value="{{ main["id"] }}"> {{ main["name"] }} </option>
{% endfor %}
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="major_p">
<option disabled selected>Major Prefix **</option>
{% for major in majors %}
<option value="{{ major["id"] }}"> {{ major["description"] }} </option>
{% endfor %}
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="minor_p">
<option disabled selected>Minor Prefix ***</option>
{% for minor in minors %}
<option value="{{ minor["id"] }}"> {{ minor["description"] }} </option>
{% endfor %}
</select>
</div>
<br>
<button class="btn btn-outline-dark btn-lg" type="submit">Add Item</button>
</form>
{% endblock %}
因此,在我朋友 (向 Scraelos 大声疾呼!:) 的帮助下,我们能够使用 Flask 的 Jsonify 功能解决这个问题,并且 Jquery。这与我最初想要实现的方法略有不同,但它更适合我的网络应用程序的一般用途。
(通过这样做,我能够消除通过“/add”路由的 GET 方法填充 select 选项的需要)
python代码:
@app.route("/options")
@login_required
def options():
wtype = request.args.get('wtype')
weapons = db.execute("SELECT id, name FROM weapons WHERE type = ?", wtype)
mains = db.execute("SELECT id, name FROM mainp WHERE type = ? OR type = 0", wtype)
majors = db.execute("SELECT id, description FROM majorp WHERE type = ? OR type = 0", wtype)
minors = db.execute("SELECT id, description FROM minorp WHERE type = ? OR type = 0", wtype)
return jsonify(weapons=weapons, mains=mains, majors=majors, minors=minors)
javascript代码:
$(document).ready(function() {
// first we hide opions 2-5 and button
$('#wname').hide();
$('#main_p').hide();
$('#major_p').hide();
$('#minor_p').hide();
$('#submitbtn').hide();
// when 1st available option is changed, we get JSON from "/options"
$('#wtype').change(function(){
$.getJSON('/options', {
wtype: $('#wtype').val()
// if request successful process data
}).done(function(data) {
// remeber selected options for later use
mainp=$('#main_p').val();
majorp=$('#major_p').val();
minorp=$('#minor_p').val();
// empty options for now...
$('#wname').empty();
$('#main_p').empty();
$('#major_p').empty();
$('#minor_p').empty();
// appending placeholder options
$('#wname').append($('<option disabled selected>Weapon Name</option>'));
$('#main_p').append($('<option disabled selected>Main Prefix ☆</option>'));
$('#major_p').append($('<option disabled selected>Major Prefix ☆☆</option>'));
$('#minor_p').append($('<option disabled selected>Minor Prefix ☆☆☆</option>'));
// appending real options available for chosen type trough itteration
$.each(data.weapons, function(key, val) {
$('#wname').append($('<option>').text(val.name).attr('value', val.id));
});
$.each(data.mains, function(key, val) {
$('#main_p').append($('<option>').text(val.name).attr('value', val.id));
});
$.each(data.majors, function(key, val) {
$('#major_p').append($('<option>').text(val.description).attr('value', val.id));
});
$.each(data.minors, function(key, val) {
$('#minor_p').append($('<option>').text(val.description).attr('value', val.id));
});
// after all new options were added to selection, this "if" condition checks if previously saved option is in new options list
if ($("#main_p option[value="+mainp+"]").length > 0){
// if true, select this option
$('#main_p').val(mainp).change();
}
if ($("#major_p option[value="+majorp+"]").length > 0){
$('#major_p').val(majorp).change();
}
if ($("#minor_p option[value="+minorp+"]").length > 0){
$('#minor_p').val(minorp).change();
}
// make select options and button fadeIn from "hide"
$('#wname').fadeIn();
$('#main_p').fadeIn();
$('#major_p').fadeIn();
$('#minor_p').fadeIn();
$('#submitbtn').fadeIn();
})
});
});
和 HTML 毕竟看起来像这样:
{% extends "layout.html" %}
{% block title %}
Add
{% endblock %}
{% block main %}
<form action="/add" method="post">
<div class="form-group">
<select class="form-control col-md-4 bg-dark text-success" name="wtype" id="wtype">
<option disabled selected>Weapon Type</option>
<option value="-1">Melee</option>
<option value="1">Ranged</option>
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="wname" id="wname">
<!-- I was able to remove below syntax, by performing table select population through Jquery code in fetch.js
<option disabled selected>Weapon Name</option>
{% for weapon in weapons %}
<option value="{{ weapon["id"] }}"> {{ weapon["name"] }} </option>
{% endfor %}
-->
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="main_p" id="main_p"></select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="major_p" id="major_p"></select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="minor_p" id="minor_p"></select>
</div>
<br>
<button class="btn btn-outline-dark btn-lg" type="submit" id="submitbtn">Add Item</button>
</form>
<script src="/static/fetch.js"></script>
{% endblock %}
也许有人会发现此解决方案有用。和平! :)
美好的一天。我真的是编程新手(3 个月),我正在尝试为我的课程期末项目添加最后一个功能。 在我的 html 页面中,我有 5 个 select 容器,第一个容器的数据来自我的 app.py 中的元组对象,其余 4 个选项数据来自 sqlite3 数据库查询。我希望这些选项相互依赖,无论用户首先 select 编辑哪个选项。 为了让您更多地了解我在说什么,所有选项都与武器类型相关(这是一个用于管理在线游戏库存的网络应用程序),此“类型”列存在于每个 table用于查询,远程武器表示为“1”,近战武器表示为“2”,两种类型均表示为“0”。 所以我是怎么理解的,我需要在一个选项被 selected 之后发出一个 json 请求,并且 return 将新的查询结果返回给 html 以便使用 javascript 处理新数据?但是接下来,当新选项将 selected 并减少变体时......我完全迷失在这里,因为我的 javascript 经验仅与 bootstrap (copy/paste )... 我希望我清楚地解释了一切,并且非常感谢一些如何做的例子。谢谢你的时间。
我的python代码:
@app.route("/add", methods=["GET", "POST"])
@login_required
def add():
# assigning user_id to session
user_id = session["user_id"]
# this will be used for future dynamic change feature
weapon_type = ("-1", "1")
if request.method == "POST":
# assigning user's input
wtype = request.form.get("wtype")
wname = request.form.get("wname")
main_p = request.form.get("main_p")
major_p = request.form.get("major_p")
minor_p = request.form.get("minor_p")
# check if input fields are blank or not valid
if not wtype or wtype not in weapon_type:
return apology("Invalid type")
if not wname:
return apology("Invalid type")
if not main_p:
return apology("Invalid type")
# adding new weapon into users_weapons table
db.execute("INSERT INTO user_weapons (user_id, weapon_id, main_id, major_id, minor_id) VALUES(?, ?, ?, ?, ?)", user_id, wname, main_p, major_p, minor_p)
return redirect("/inventory")
else:
# adding options for select forms
weapons = db.execute("SELECT id, name FROM weapons")
mains = db.execute("SELECT id, name FROM mainp")
majors = db.execute("SELECT id, description FROM majorp")
minors = db.execute("SELECT id, description FROM minorp")
return render_template("add.html", weapons=weapons, mains=mains, majors=majors, minors=minors)
我的html代码:
{% block main %}
<form action="/add" method="post">
<div class="form-group">
<select class="form-control col-md-4 bg-dark text-success" name="wtype">
<option disabled selected>Weapon Type</option>
<option value="-1">Melee</option>
<option value="1">Ranged</option>
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="wname">
<option disabled selected>Weapon Name</option>
{% for weapon in weapons %}
<option value="{{ weapon["id"] }}"> {{ weapon["name"] }} </option>
{% endfor %}
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="main_p">
<option disabled selected>Main Prefix *</option>
{% for main in mains %}
<option value="{{ main["id"] }}"> {{ main["name"] }} </option>
{% endfor %}
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="major_p">
<option disabled selected>Major Prefix **</option>
{% for major in majors %}
<option value="{{ major["id"] }}"> {{ major["description"] }} </option>
{% endfor %}
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="minor_p">
<option disabled selected>Minor Prefix ***</option>
{% for minor in minors %}
<option value="{{ minor["id"] }}"> {{ minor["description"] }} </option>
{% endfor %}
</select>
</div>
<br>
<button class="btn btn-outline-dark btn-lg" type="submit">Add Item</button>
</form>
{% endblock %}
因此,在我朋友 (向 Scraelos 大声疾呼!:) 的帮助下,我们能够使用 Flask 的 Jsonify 功能解决这个问题,并且 Jquery。这与我最初想要实现的方法略有不同,但它更适合我的网络应用程序的一般用途。
(通过这样做,我能够消除通过“/add”路由的 GET 方法填充 select 选项的需要)
python代码:
@app.route("/options")
@login_required
def options():
wtype = request.args.get('wtype')
weapons = db.execute("SELECT id, name FROM weapons WHERE type = ?", wtype)
mains = db.execute("SELECT id, name FROM mainp WHERE type = ? OR type = 0", wtype)
majors = db.execute("SELECT id, description FROM majorp WHERE type = ? OR type = 0", wtype)
minors = db.execute("SELECT id, description FROM minorp WHERE type = ? OR type = 0", wtype)
return jsonify(weapons=weapons, mains=mains, majors=majors, minors=minors)
javascript代码:
$(document).ready(function() {
// first we hide opions 2-5 and button
$('#wname').hide();
$('#main_p').hide();
$('#major_p').hide();
$('#minor_p').hide();
$('#submitbtn').hide();
// when 1st available option is changed, we get JSON from "/options"
$('#wtype').change(function(){
$.getJSON('/options', {
wtype: $('#wtype').val()
// if request successful process data
}).done(function(data) {
// remeber selected options for later use
mainp=$('#main_p').val();
majorp=$('#major_p').val();
minorp=$('#minor_p').val();
// empty options for now...
$('#wname').empty();
$('#main_p').empty();
$('#major_p').empty();
$('#minor_p').empty();
// appending placeholder options
$('#wname').append($('<option disabled selected>Weapon Name</option>'));
$('#main_p').append($('<option disabled selected>Main Prefix ☆</option>'));
$('#major_p').append($('<option disabled selected>Major Prefix ☆☆</option>'));
$('#minor_p').append($('<option disabled selected>Minor Prefix ☆☆☆</option>'));
// appending real options available for chosen type trough itteration
$.each(data.weapons, function(key, val) {
$('#wname').append($('<option>').text(val.name).attr('value', val.id));
});
$.each(data.mains, function(key, val) {
$('#main_p').append($('<option>').text(val.name).attr('value', val.id));
});
$.each(data.majors, function(key, val) {
$('#major_p').append($('<option>').text(val.description).attr('value', val.id));
});
$.each(data.minors, function(key, val) {
$('#minor_p').append($('<option>').text(val.description).attr('value', val.id));
});
// after all new options were added to selection, this "if" condition checks if previously saved option is in new options list
if ($("#main_p option[value="+mainp+"]").length > 0){
// if true, select this option
$('#main_p').val(mainp).change();
}
if ($("#major_p option[value="+majorp+"]").length > 0){
$('#major_p').val(majorp).change();
}
if ($("#minor_p option[value="+minorp+"]").length > 0){
$('#minor_p').val(minorp).change();
}
// make select options and button fadeIn from "hide"
$('#wname').fadeIn();
$('#main_p').fadeIn();
$('#major_p').fadeIn();
$('#minor_p').fadeIn();
$('#submitbtn').fadeIn();
})
});
});
和 HTML 毕竟看起来像这样:
{% extends "layout.html" %}
{% block title %}
Add
{% endblock %}
{% block main %}
<form action="/add" method="post">
<div class="form-group">
<select class="form-control col-md-4 bg-dark text-success" name="wtype" id="wtype">
<option disabled selected>Weapon Type</option>
<option value="-1">Melee</option>
<option value="1">Ranged</option>
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="wname" id="wname">
<!-- I was able to remove below syntax, by performing table select population through Jquery code in fetch.js
<option disabled selected>Weapon Name</option>
{% for weapon in weapons %}
<option value="{{ weapon["id"] }}"> {{ weapon["name"] }} </option>
{% endfor %}
-->
</select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="main_p" id="main_p"></select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="major_p" id="major_p"></select>
<br>
<br>
<select class="form-control col-md-4 bg-dark text-success" name="minor_p" id="minor_p"></select>
</div>
<br>
<button class="btn btn-outline-dark btn-lg" type="submit" id="submitbtn">Add Item</button>
</form>
<script src="/static/fetch.js"></script>
{% endblock %}
也许有人会发现此解决方案有用。和平! :)