Flask动态URL格式不符合预期,如何修正?
Flask动态路由链接格式错误解决办法
问题现象
尝试通过for循环生成带动态锚点的div,预期URL格式为http://127.0.0.1:5000/tienda/2,但实际生成的是http://127.0.0.1:5000/tienda?id_producto=2。
现有代码
Python路由代码
def sql_request(data, sql_stmt): try: cursor = conexion.connection.cursor() sql = sql_stmt cursor.execute(sql) productos = cursor.fetchall() data['productos'] = productos except Exception as ex: print(f"Esta es la excepción: {ex}") data['mensaje'] = "Error" return data @app.route('/tienda') def tienda(): return render_template("tienda.html") @app.route('/tienda/<int:id_producto>') def item(id_producto): data = {} sql_stmt = f"SELECT * FROM productos WHERE ID_Producto = {id_producto}" data = sql_request(data, sql_stmt) return render_template("item.html", data=data)
Jinja2 HTML代码
{% for c in data.productos %} <a class="featured-product-card" href="{{ url_for('tienda', id_producto=c[0]) }}"> <h3>{{ c[1] }}</h3> <img src="{{ url_for('static', filename = c[2])}}"> <p>$ {{ c[3] }}</p> <p>{{ c[4] }}</p> </a> {% endfor %}
问题原因
url_for的第一个参数是视图函数名,不是路由路径。当前调用url_for('tienda', id_producto=c[0])匹配的是@app.route('/tienda')对应的tienda函数,这个路由没有定义URL参数,所以Flask会把id_producto作为查询参数附加到URL后,形成/tienda?id_producto=2的格式。而带动态参数的路由/tienda/<int:id_producto>对应的视图函数是item,不是tienda。
解决方案
修改Jinja2代码中的url_for调用,将视图函数名改为item:
{% for c in data.productos %} <a class="featured-product-card" href="{{ url_for('item', id_producto=c[0]) }}"> <h3>{{ c[1] }}</h3> <img src="{{ url_for('static', filename = c[2])}}"> <p>$ {{ c[3] }}</p> <p>{{ c[4] }}</p> </a> {% endfor %}
额外建议:规避SQL注入风险
当前SQL语句使用字符串拼接f"SELECT * FROM productos WHERE ID_Producto = {id_producto}",存在SQL注入风险,建议改用参数化查询:
修改sql_request函数
def sql_request(data, sql_stmt, params=None): try: cursor = conexion.connection.cursor() sql = sql_stmt if params: cursor.execute(sql, params) else: cursor.execute(sql) productos = cursor.fetchall() data['productos'] = productos except Exception as ex: print(f"Esta es la excepción: {ex}") data['mensaje'] = "Error" return data
修改item视图函数
@app.route('/tienda/<int:id_producto>') def item(id_producto): data = {} sql_stmt = "SELECT * FROM productos WHERE ID_Producto = %s" data = sql_request(data, sql_stmt, (id_producto,)) return render_template("item.html", data=data)
内容的提问来源于stack exchange,提问作者alain86
相关产品推荐
相关产品推荐

