jquery 如何使用Flask创建两个依赖的动态下拉列表

vshtjzan  于 2023-06-29  发布在  jQuery
关注(0)|答案(1)|浏览(177)

我在Flask中修改了以下示例代码https://tutorial101.blogspot.com/2021/01/python-flask-dynamic-loading-of.html,以使用SQlite数据库。www.example.com的目的app.py是显示汽车品牌的选项,然后按品牌显示可用的型号。py使用两个下拉框,用户可以从中进行选择。原始源代码是用Flask编写的,用于访问MySQL数据库。我修改了app.py的代码以使用SQlite db。
app.py运行良好。我可以想象两个下拉框的选项。当我选择一个汽车品牌时,应用程序会用可用的车型更新第二个下拉框。

当按下提交按钮时,我希望显示值 在两个选择中。具体地,哪个是所选择的汽车品牌,哪个是所选择的模型。
我已经在代码中包含了一条指令来显示汽车品牌的值,同时也显示了 与汽车型号相对应。但是,我无法找到一种方法来获得所选车型的价值。

我如何才能做到这一点?
谢谢
注:* 问题文本已编辑为更具体。问题的本质没有改变。*
我附上源代码和使用的模板。
app.py:

# flask sqlalchemy

from flask_sqlalchemy  import SQLAlchemy

# app.py

from flask import Flask, render_template, request, jsonify

app = Flask(__name__)
    
app.config['SECRET_KEY'] = "caircocoders-ednalan"

# sqlite config
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///testingdb.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Bind the instance to the 'app.py' Flask application
db = SQLAlchemy(app)
    

class Carbrands(db.Model):
    __tablename__ = 'carbrands' 
    brand_id = db.Column(db.Integer, primary_key = True)
    brand_name = db.Column(db.String(250))

    def __repr__(self):
    
        return '\n brand_id: {0} brand_name: {1}'.format(self.brand_id, self.brand_name)

    def __str__(self):

        return '\n brand_id: {0} brand_name: {1}'.format(self.brand_id, self.brand_name)

class Carmodels(db.Model):
    __tablename__ = 'carmodels' 
    model_id = db.Column(db.Integer, primary_key = True)
    brand_id = db.Column(db.Integer)
    car_models = db.Column(db.String(250))

    def __repr__(self):
    
        return '\n model_id: {0} brand_id: {1} car_models: {2}'.format(self.model_id, self.brand_id, self.car_models)

    def __str__(self):

        return '\n model_id: {0} brand_id: {1} car_models: {2}'.format(self.model_id, self.brand_id, self.car_models)



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

    q = Carbrands.query.all()
    print(q)

    carbrands = q

    return render_template('index.html', carbrands=carbrands)

# response.html 
@app.route("/get_child_categories", methods=["POST","GET"])
def get_child_categories():
  
    if request.method == 'POST':
        parent_id = request.form['parent_id']

        car = Carbrands.query.filter_by(brand_id=parent_id).first()
        print("Car brand '{0}' parent_id '{1}'".format(car.brand_name, parent_id))
        carmodels = Carmodels.query.filter_by(brand_id=parent_id).all()
        print(carmodels)

    return jsonify({'htmlresponse': render_template('response.html', carmodels=carmodels)})

if __name__ == "__main__":
    app.run(debug=True)

index.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python Flask Dynamic Loading of ComboBox using jQuery Ajax and SQlite</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
 $('#search_category_id').change(function(){
        $.post("/get_child_categories", {
         parent_id: $('#search_category_id').val()
        }, function(response){ 
                $('#show_sub_categories').html(response);
                $('#show_sub_categories').append(response.htmlresponse);
                
        });
        return false;
    });
}); 
</script>
</head>
<body>
     <div class="container">
        <div class="row">
            <div class="col-lg-2"></div>
        <div class="col-lg-8">
        <h3 align="center">Python Flask Dynamic Loading of ComboBox using jQuery Ajax and SQlite</h3>
        <form action="#" name="form" id="form" method="post">
            <div class="form-group">
                <label>Select Category</label>
                <select name="search_category"  id="search_category_id" class="form-control">
                    <option value="" selected="selected"></option>
                    {% for row in carbrands %}
                    <option value='{{row.brand_id}}'>{{row.brand_name}}</option>
                    {% endfor %}
                    </select> 
            </div>
            <div id="show_sub_categories"></div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
        </div>
        <div class="col-lg-2"></div>
    </div>
</div>
</body>
</html>

response.html:

<div class="form-group">
  <label>Select Sub Category</label>
  <select name="sub_category"  id="sub_category_id" class="form-control">
     <option value="" selected="selected"></option>
      {% for row in carmodels %} 
      <option value="{{row.model_id}}">{{row.car_models}}</option>
      {% endfor %}
  </select> 
</div>
epggiuax

epggiuax1#

我已经找到解决办法了。我附上了源代码作为参考,以防有人对解决方案感兴趣。这个问题意味着研究工作。

在截图中可以看到,显示了选择汽车品牌和选择汽车型号的选项。

当选择汽车品牌时,第二个下拉框显示与汽车品牌对应的车型列表。

当按下过程选择按钮时,应用程序显示指示已选择的汽车品牌和汽车型号的消息。

解决方案是实现对包含汽车品牌和型号的数据库表的阅读。这些信息被转换成一个python字典,以提供给两个下拉框。当选择汽车品牌时,应用程序在第二个下拉框中显示与该汽车品牌对应的汽车型号,参见:@app.route('/update_dropdown')
https://api.jquery.com/jquery.getjson/文档对解决方案至关重要。特别是$ .getJSON('/
update_dropdown',...以及$ .getJSON('/_ process_data',…Flask中很多关于下拉框动态更新的例子都是演示了下拉框是如何实现的,但是没有提到如何获取选中的数据;对继续这个过程很重要。在这种情况下,该解决方案包括在Flask中实现动态下拉框和处理所选值的所有细节。
在研究了可能的解决方案后,我发现了一个类似问题的链接。所以,我研究了解决方案,并根据我的需要进行了调整。我承认链接的作者:如何在不刷新页面的情况下在flask中创建链式selectfield?感谢你的宝贵贡献没有这种指导,就不可能成功地解决这个问题。
app.py:

# SEE: https://stackoverflow.com/questions/25978879/how-to-create-chained-selectfield-in-flask-without-refreshing-the-page/49969686#49969686

# flask sqlalchemy

from flask_sqlalchemy  import SQLAlchemy
import sqlalchemy

# app.py

from flask import Flask, render_template, request, jsonify
import json

# Initialize the Flask application
app = Flask(__name__)
    
app.config['SECRET_KEY'] = "caircocoders-ednalan"

# sqlite config
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///cars.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Bind the instance to the 'app.py' Flask application
db = SQLAlchemy(app)
    

class Carbrands(db.Model):
    __tablename__ = 'carbrands' 
    brand_id = db.Column(db.Integer, primary_key = True)
    brand_name = db.Column(db.String(250))

    def __repr__(self):
    
        return '\n brand_id: {0} brand_name: {1}'.format(self.brand_id, self.brand_name)

    def __str__(self):

        return '\n brand_id: {0} brand_name: {1}'.format(self.brand_id, self.brand_name)

class Carmodels(db.Model):
    __tablename__ = 'carmodels' 
    model_id = db.Column(db.Integer, primary_key = True)
    brand_id = db.Column(db.Integer)
    car_model = db.Column(db.String(250))

    def __repr__(self):
    
        return '\n model_id: {0} brand_id: {1} car_model: {2}'.format(self.model_id, self.brand_id, self.car_model)

    def __str__(self):

        return '\n model_id: {0} brand_id: {1} car_model: {2}'.format(self.model_id, self.brand_id, self.car_model)

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

    # Create a dictionary (myDict) where the key is 
    # the name of the brand, and the list includes the names of the car models
    # 
    # Read from the database the list of cars and the list of models. 
    # With this information, build a dictionary that includes the list of models by brand. 
    # This dictionary is used to feed the drop down boxes of car brands and car models that belong to a car brand.
    # 
    # Example:
    #
    # {'Toyota': ['Tercel', 'Prius'], 
    #  'Honda': ['Accord', 'Brio']}

    carbrands = Carbrands.query.all()
    # Create an empty dictionary
    myDict = {}
    for p in carbrands:
    
        key = p.brand_name
        brand_id = p.brand_id

        # Select all car models that belong to a car brand
        q = Carmodels.query.filter_by(brand_id=brand_id).all()
    
        # build the structure (lst_c) that includes the names of the car models that belong to the car brand
        lst_c = []
        for c in q:
            lst_c.append( c.car_model )
        myDict[key] = lst_c
    
    
    class_entry_relations = myDict
                        
    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 the car brand: {} and the model: {}.".format(selected_class, selected_entry))



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

    """
    initialize drop down menus
    """

    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)

index.html:

<!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">
        <h1 class="text-center text-muted">Dynamic dropdowns</h1>
      </div>

      <br><br><br>

      <div class="row">
        <div class="form-group col-xs-6">
          <label for="all_classes">Select a car</label>
          <select class="form-control" style="color: white; background: #34568B;" 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 a model</label>
          <select class="form-control" style="color:white; background:#009B77;" id="all_entries">
            {% for o in all_entries %}
                    <option value="{{ o }}">{{ o }}</option>
            {% endfor %}
          </select>
        </div>
      </div>

      <div>
        <button type="button" style="color:white; background:#3498DB;" 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>

create_tables_and_data.sql:

--
-- Table structure for table `carbrands`
--

CREATE TABLE CARBRANDS ( 
    BRAND_ID INT PRIMARY KEY NOT NULL,
    BRAND_NAME CHAR(250)
);

--
-- Dumping data for table `carbrands`
--

INSERT INTO CARBRANDS (BRAND_ID, BRAND_NAME) VALUES (1, 'Toyota');
INSERT INTO CARBRANDS (BRAND_ID, BRAND_NAME) VALUES (2, 'Honda');
INSERT INTO CARBRANDS (BRAND_ID, BRAND_NAME) VALUES (3, 'Suzuki');
INSERT INTO CARBRANDS (BRAND_ID, BRAND_NAME) VALUES (4, 'Mitsubishi');
INSERT INTO CARBRANDS (BRAND_ID, BRAND_NAME) VALUES (5, 'Hyundai');
--
-- Table structure for table `carmodels`
--

CREATE TABLE CARMODELS (
    MODEL_ID INT PRIMARY KEY NOT NULL,
    BRAND_ID INT NOT NULL,
    CAR_MODEL CHAR(250) NOT NULL
);

--
-- Dumping data for table `carmodels`
--

INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (1, 1, 'Toyota Corolla');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (2, 1, 'Toyota Camry');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (3, 1, 'Toyota Yaris');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (4, 1, 'Toyota Sienna');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (5, 1, 'Toyota RAV4');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (6, 1, 'Toyota Highlander');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (7, 2, 'Honda HR-V');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (8, 2, 'Honda Odyssey');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (9, 3, 'Swift');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (10, 3, 'Celerio');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (11, 3, 'Ertiga');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (12, 3, 'Vitara');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (13, 4, 'Mirage');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (14, 4, 'Mirage G4');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (15, 4, 'Xpander Cross');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (16, 4, 'Montero Sport');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (17, 4, 'Strada Athlete');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (18, 5, 'Reina ');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (19, 5, 'Accent');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (20, 5, 'Elantra');
INSERT INTO CARMODELS (MODEL_ID, BRAND_ID, CAR_MODEL) VALUES (21, 5, 'Tucson');

相关问题