前端从静态JSON迁移至数据库的技术方案咨询(Flask+JS)
基于Python+Flask的数据库动态交互方案
核心逻辑
前端JS仅与Flask后端API通信,所有数据库操作由后端完成,完全避免前端直接接触数据库凭据和结构,从根源解决信息暴露问题。
具体实现步骤
配置Flask与SQL数据库连接
推荐用Flask-SQLAlchemy(ORM工具)简化数据库操作,先安装依赖:pip install flask-sqlalchemy pymysql然后在Flask应用中配置数据库连接:
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 替换为你的MySQL账号、密码、数据库名 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://your_username:your_password@localhost/your_db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app)定义级联数据模型
针对大陆→国家→城市的层级结构,创建对应的数据模型:class Continent(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), unique=True) countries = db.relationship('Country', backref='continent', lazy=True) class Country(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), unique=True) continent_id = db.Column(db.Integer, db.ForeignKey('continent.id')) cities = db.relationship('City', backref='country', lazy=True) class City(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) country_id = db.Column(db.Integer, db.ForeignKey('country.id'))编写API接口提供数据
为前端提供三级联动所需的接口,按需返回对应层级的数据:from flask import jsonify # 获取所有大陆列表 @app.route('/api/continents') def get_continents(): continents = Continent.query.all() return jsonify([{'id': c.id, 'name': c.name} for c in continents]) # 根据大陆ID获取对应国家列表 @app.route('/api/countries/<int:continent_id>') def get_countries(continent_id): countries = Country.query.filter_by(continent_id=continent_id).all() return jsonify([{'id': c.id, 'name': c.name} for c in countries]) # 根据国家ID获取对应城市列表 @app.route('/api/cities/<int:country_id>') def get_cities(country_id): cities = City.query.filter_by(country_id=country_id).all() return jsonify([{'id': c.id, 'name': c.name} for c in cities])前端JS调用API实现动态联动
用原生JS或Axios调用后端API,实现下拉框的动态更新:// 初始化加载大陆列表 fetch('/api/continents') .then(res => res.json()) .then(data => { const continentSel = document.getElementById('continent'); data.forEach(item => { const opt = document.createElement('option'); opt.value = item.id; opt.textContent = item.name; continentSel.appendChild(opt); }); }); // 监听大陆选择变化,加载对应国家 document.getElementById('continent').addEventListener('change', function() { const contId = this.value; if (!contId) return; fetch(`/api/countries/${contId}`) .then(res => res.json()) .then(data => { const countrySel = document.getElementById('country'); countrySel.innerHTML = '<option value="">请选择国家</option>'; data.forEach(item => { const opt = document.createElement('option'); opt.value = item.id; opt.textContent = item.name; countrySel.appendChild(opt); }); // 清空城市下拉框 document.getElementById('city').innerHTML = '<option value="">请选择城市</option>'; }); }); // 监听国家选择变化,加载对应城市 document.getElementById('country').addEventListener('change', function() { const countryId = this.value; if (!countryId) return; fetch(`/api/cities/${countryId}`) .then(res => res.json()) .then(data => { const citySel = document.getElementById('city'); citySel.innerHTML = '<option value="">请选择城市</option>'; data.forEach(item => { const opt = document.createElement('option'); opt.value = item.id; opt.textContent = item.name; citySel.appendChild(opt); }); }); });
优化建议
- 添加缓存:对大陆、国家这类更新频率低的数据,用Flask-Caching做缓存,减少数据库查询次数,提升响应速度。
- 参数验证:后端接口对传入的ID参数做合法性校验,防止非法请求。
- 分页处理:如果城市数据量极大,可实现分页返回,避免一次性加载过多数据导致前端卡顿。
内容的提问来源于stack exchange,提问作者erotski
相关产品推荐
相关产品推荐

