【问题标题】:Flask - Generate child choices after selecting parentFlask - 选择父项后生成子项选择
【发布时间】:2018-10-25 19:22:12
【问题描述】:

我使用flask_sqlalchemy、flask_wtf、Jinja2 + 引导程序 并在models.py 开设国家、城市课程
在模板中,我有两个下拉列表,一个用于国家,另一个用于城市,
我想如果从第一个 selectfield 中选择 A country ,第二个 selectfield 只填充 A country 的城市
如果更改国家/地区,则城市选择字段会根据国家/地区选择更改城市,并且城市有一些区域和城市选择字段,并且区域选择字段是相关的
韩德尔这个案子如何?保持性能良好
但在这种情况下,使用什么是正确的(SelectField 或 QuerySelectField)
(我不知道这种情况如何写routes.py)
模型.py

class Country(db.Model):
   id = db.Column(db.Integer, primary_key=True, autoincrement=True)
   name = db.Column(db.String(10), unique=True)
   code = db.Column(db.String(4), unique=True)
   cities = db.relationship('City', backref='country', lazy=True)

class City(db.Model):
   id = db.Column(db.Integer, primary_key=True, autoincrement=True)
   name = db.Column(db.String(10))
   code = db.Column(db.String(4))
   country_id = db.Column(db.Integer, db.ForeignKey('country.id'), nullable=False)
   areas = db.relationship('Area', backref='city', lazy=True)

class Area(db.Model):
   id = db.Column(db.Integer, primary_key=True, autoincrement=True)
   name = db.Column(db.String(20))
   code = db.Column(db.String(5))
   city_id = db.Column(db.Integer, db.ForeignKey('city.id'), nullable=False)

forms.py

address_country = SelectField('Country', validators=[DataRequired()], render_kw={"placeholder": _('Country')})
address_city = SelectField('City', validators=[DataRequired()], render_kw={"placeholder": _('City')})
address_area = SelectField('Area', validators=[DataRequired()], render_kw={"placeholder": _('Area')})

index.html

<div class="form-row">
  <div class="form-group col-md-3">
    <label> {{ form.address_country.label }}</label>
       {{ form.address_country(class="form-control") }}
  </div>
  <div class="form-group col-md-3">
    <label> {{ form.address_city.label }}</label>
       {{ form.address_city(class="form-control") }}
  </div>
  <div class="form-group col-md-3">
    <label> {{ form.address_area.label }}</label>
       {{ form.address_area(class="form-control") }}
  </div>
</div>

【问题讨论】:

    标签: flask flask-sqlalchemy flask-wtforms wtforms


    【解决方案1】:

    使用 AJAX 和 QuerySelectField 返回所选国家/地区的城市。

    import os
    from flask import Flask, render_template, session, request
    from flask_sqlalchemy import SQLAlchemy
    from flask_wtf import FlaskForm, CSRFProtect
    from wtforms.fields import SubmitField
    from wtforms.ext.sqlalchemy.fields import QuerySelectField
    
    
    app = Flask(__name__)
    
    basedir = os.path.abspath(os.path.dirname(__file__))
    
    app = Flask(__name__)
    
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = 'True'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'main.db')
    app.config['SECRET_KEY'] = '^%huYtFd90;90jjj'
    
    
    db = SQLAlchemy(app)
    csrf = CSRFProtect(app)
    
    
    def the_factory():
        return Country.query
    
    
    def city_factory():
        return [City.query.get(item) for item in session['cities']]
    
    
    class Country(db.Model):
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(10), unique=True)
        cities = db.relationship('City', backref='country', lazy=True)
    
    
    class City(db.Model):
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(10))
        country_id = db.Column(db.Integer, db.ForeignKey('country.id'), nullable=False)
        areas = db.relationship('Area', backref='city', lazy=True)
    
    
    class Area(db.Model):
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(20))
        code = db.Column(db.String(5))
        city_id = db.Column(db.Integer, db.ForeignKey('city.id'), nullable=False)
    
    
    class SelectCountryForm(FlaskForm):
        all_countries = QuerySelectField(query_factory=the_factory, get_label='name', render_kw={"onclick": "cityFunction();"})
        submit = SubmitField()
    
    
    class SelectCityForm(FlaskForm):
        cities = QuerySelectField(query_factory=city_factory, get_label='name')
        submit = SubmitField()
    
    
    @app.route('/get-cities', methods=['GET', 'POST'])
    def get_cities():
        selected_country = request.get_json()
        selected_cities = City.query.filter_by(country_id=selected_country['selected_country']).all()
        session['cities'] = [item.id for item in selected_cities]
        return render_template('data.html', form=SelectCityForm())
    
    
    @app.route('/', methods=['GET', 'POST'])
    def search():
        return render_template('show.html', form=SelectCountryForm())
    
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    show.html

    {% from '_helper.html' import render_field with context %}
    {% extends 'base.html' %}
    {% block content %}
    <div id="foo">
        <form method="post">
            {{ form.csrf_token() }}
            {{ render_field(form.all_countries) }}
        </form>
    </div>
    {% endblock %}
    

    selected-cities.html

    {% from '_helper.html' import render_field with context %}
    {% block content%}
    <div id="bar">
        <form method="post">
            {{ form.csrf_token() }}
            {{ render_field(form.cities) }}
        </form>
    </div>
    {% endblock %}
    

    .js

    function cityFunction() {
        var csrftoken = $('meta[name=csrf-token]').attr('content')
    
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken)
                }
            }
        })
    
        var my = $('#all_countries option:selected').val()
        var data1 = {'selected_country': my}
        $.ajax({
            url: '/get-cities',
            data: JSON.stringify(data1),
            method: 'POST',
            contentType: 'application/json',
            success: function(data) {
                $('#foo').replaceWith(data);
            }
        });
    };
    

    【讨论】:

    • 经过测试,当国家改变时如何添加空白元素,因为选择国家时必须点击或重新选择项目才能提交
    • 在cities = QuerySelectField(query_factory=city_factory, get_label='name', allow_blank=True) 中添加allow_blank=True 选择无
    猜你喜欢
    • 2012-08-01
    • 2016-02-12
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 2015-02-17
    • 2017-03-06
    • 1970-01-01
    • 2020-02-24
    相关资源
    最近更新 更多