我使用flask_sqlalchemy
,flask_wtf
,Jinja2
+引导程序
并且在models.py
中有country,city类
在模板中,我有两个下拉菜单,一个用于国家,另一个用于城市,
我想从第一个选择字段中选择一个国家,第二个选择字段仅填充一个国家的城市
如果更改国家/地区,则城市选择字段会根据国家/地区选择来更改城市,并且城市也包含某些区域和城市选择字段,而区域选择字段相关
如何处理这种情况?保持良好的表现
但是在这种情况下,使用什么是正确的(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>
答案 0 :(得分: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);
}
});
};