Flask本地正常的GET请求数据传递逻辑在服务器端报错的问题求助
Flask本地正常的GET请求数据传递逻辑在服务器端报错的问题求助
兄弟,你的问题根源其实很明确:本地环境里URL没有被严格编码,但服务器端会自动对URL路径中的特殊字符做URL编码,导致你拿到的city_info是编码后的字符串(比如%7B就是{的URL编码,%20是空格),而eval根本认不出这种编码后的格式,自然就报语法错误了。而且还有个大问题:用eval处理用户传入的参数非常不安全,万一有人构造恶意字符串,直接就能执行恶意代码!
给你几个靠谱的解决方案,按推荐程度排序:
方案1:用JSON+Base64编码传递数据(最安全可靠)
把字典先序列化成JSON字符串,再用Base64编码,这样既避免了URL编码破坏格式,又提升了安全性(虽然不是绝对安全,但比eval强太多)。
修改get_destination_data函数:
import json import base64 from flask import url_for, jsonify, request @app.route('/get_destination_data', methods=['GET', 'POST']) def get_destination_data(): data = request.get_json() # 把字典转成JSON字符串,再Base64编码 json_str = json.dumps(data) encoded_data = base64.b64encode(json_str.encode('utf-8')).decode('utf-8') return jsonify({'redirect': url_for("show_destination_info", city_info=encoded_data)})
修改show_destination_info函数:
import json import base64 from flask import render_template, abort from flask_login import current_user from your_app_model import UserLists # 替换成你的模型导入 @app.route('/show_destination_info/<city_info>', methods=['GET', 'POST']) def show_destination_info(city_info): try: # 先Base64解码,再转成字典 decoded_str = base64.b64decode(city_info).decode('utf-8') data = json.loads(decoded_str) except (base64.binascii.Error, json.JSONDecodeError): # 处理解码失败的情况,返回400错误 abort(400, description="Invalid data format") return render_template('user_city-info.html', data=data, lists=UserLists.query.filter_by(user_id=current_user.id).all())
方案2:拆分数据为URL查询参数(最直观)
如果你的数据字段不多,直接把字典的键值对拆成URL的查询参数,不用放在路径里,这样就不会有编码问题了。
修改get_destination_data函数:
from flask import url_for, jsonify, request @app.route('/get_destination_data', methods=['GET', 'POST']) def get_destination_data(): data = request.get_json() # 直接把字典拆成查询参数传入url_for return jsonify({'redirect': url_for("show_destination_info", **data)})
修改路由和show_destination_info函数:
from flask import render_template, request from flask_login import current_user from your_app_model import UserLists # 去掉路径里的<city_info>,改成接收查询参数 @app.route('/show_destination_info', methods=['GET', 'POST']) def show_destination_info(): # 从查询参数里逐个取出字段,还可以指定类型 data = { 'city_name': request.args.get('city_name'), 'country_name': request.args.get('country_name'), 'id': request.args.get('id', type=int), # 把id转成整数 'state_prov': request.args.get('state_prov') } # 可以加个校验,确保必要字段存在 if not data['city_name'] or not data['id']: abort(400, description="Missing required parameters") return render_template('user_city-info.html', data=data, lists=UserLists.query.filter_by(user_id=current_user.id).all())
方案3:改用POST请求传递数据(适合前后端交互场景)
如果你的跳转是前端发起的,其实可以不用通过URL传数据,直接用POST请求把JSON数据发给show_destination_info,这样完全避免URL长度限制和编码问题。
前端示例(假设用JavaScript):
// 拿到data后,直接POST请求 fetch('/show_destination_info', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify(data) }) .then(response => response.text()) .then(html => { // 把返回的模板内容插入页面,或者直接跳转(如果后端还是要渲染模板的话) document.body.innerHTML = html; });
修改后端show_destination_info函数:
from flask import render_template, request, abort from flask_login import current_user from your_app_model import UserLists @app.route('/show_destination_info', methods=['GET', 'POST']) def show_destination_info(): if request.method == 'POST': data = request.get_json() if not data: abort(400, description="Invalid JSON data") else: # 兼容GET请求的情况(如果需要的话) data = {} return render_template('user_city-info.html', data=data, lists=UserLists.query.filter_by(user_id=current_user.id).all())
最后再强调下:永远不要用eval处理用户传入的任何数据,这是严重的安全漏洞!上面的方案都替换掉了eval,既解决了服务器端的编码问题,又提升了代码安全性。
备注:内容来源于stack exchange,提问作者rumnen
相关产品推荐
相关产品推荐

