Flask-选择父项后生成子选项

Flask-选择父项后生成子选项,flask,flask-sqlalchemy,flask-wtforms,wtforms,Flask,Flask Sqlalchemy,Flask Wtforms,Wtforms,我使用flask_sqlalchemy、flask_wtf、Jinja2+引导 在models.py中有乡村和城市课程 在模板中,我有两个下拉列表,一个用于国家,另一个用于城市, 我想从第一个选择字段中选择一个国家,第二个选择字段只填充一个国家的城市 如果更改国家,则城市选择字段会根据国家选择更改城市,并且城市有一些区域和城市选择字段以及区域选择字段是相关的 汉德尔如何处理这个案子?保持良好的性能 但在这种情况下,使用SelectField或QuerySelectField的正确方法是什么 我不

我使用flask_sqlalchemy、flask_wtf、Jinja2+引导 在models.py中有乡村和城市课程 在模板中,我有两个下拉列表,一个用于国家,另一个用于城市, 我想从第一个选择字段中选择一个国家,第二个选择字段只填充一个国家的城市 如果更改国家,则城市选择字段会根据国家选择更改城市,并且城市有一些区域和城市选择字段以及区域选择字段是相关的 汉德尔如何处理这个案子?保持良好的性能 但在这种情况下,使用SelectField或QuerySelectField的正确方法是什么 我不知道如何为这种情况编写routes.py models.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>
使用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 %}

测试后,如何在国家/地区发生变化时添加空白元素,因为在选择国家/地区时必须单击或重新选择要提交的项目。您可以通过添加允许\u blank=True in cities=QuerySelectFieldquery\u factory=city\u factory,获取\u label='name',允许\u blank=True来选择无
{% 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 %}
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);
        }
    });
};