无法在HTML中调用Netlify部署的Python预测函数问题排查
问题排查:Netlify部署的Python函数与前端交互异常
我尝试在index.html中调用部署于Netlify的PredictedLocation.py预测函数,期望实现获取用户输入的预算、城市、房产类型、周期后,返回对应房产的预测价格并在地图标注位置的功能,但目前无法正常运行。以下是我的代码,请帮忙排查问题:
PredictedLocation.py代码
import pandas as pd from sklearn.ensemble import RandomForestRegressor import folium import webbrowser import tempfile def filter_data(data, budget, city, property_type): filtered_data = data.loc[(data['city'] == city) & (data['property_type'] == property_type) & (data['price'] <= budget)] return filtered_data def predict_price(filtered_data, period): features = ['beds', 'baths'] X = filtered_data[features] y = filtered_data['price'] model = RandomForestRegressor(n_estimators=100, random_state=42) model.fit(X, y) predicted_price = model.predict([[3, 2], [4, 3], [3, 2], [4, 3]]) predicted_price_period = predicted_price[int(period)-1] return predicted_price_period def predict_location(data, budget, city, property_type): filtered_data = filter_data(data, budget, city, property_type) # 获取周期输入 period = input("Enter the period (in months): ") predicted_price_period = predict_price(filtered_data, period) # 以筛选后第一个房产为中心创建地图 center_lat = filtered_data.iloc[0]['latitude'] center_lon = filtered_data.iloc[0]['longitude'] map_location = [center_lat, center_lon] m = folium.Map(location=map_location, zoom_start=15) # 为每个符合条件的房产添加标记 for index, row in filtered_data.iterrows(): price = row['price'] lat = row['latitude'] lon = row['longitude'] tooltip = f"Price: {price} PKR" folium.Marker([lat, lon], tooltip=tooltip).add_to(m) # 添加预测位置标记 predicted_lat = filtered_data.iloc[0]['latitude'] + 0.001 predicted_lon = filtered_data.iloc[0]['longitude'] + 0.001 predicted_tooltip = f"Predicted Price: {predicted_price_period:.2f} PKR" folium.Marker([predicted_lat, predicted_lon], tooltip=predicted_tooltip, icon=folium.Icon(color='green')).add_to(m) # 保存地图到临时HTML文件 temp_file = tempfile.NamedTemporaryFile(suffix='.html', delete=False) temp_file.close() m.save(temp_file.name) # 打开地图并打印预测价格 webbrowser.open('file://' + temp_file.name, new=2) print(f"The predicted price for a {property_type.lower()} in {city} with a period of {period} months is approximately {predicted_price_period:.2f} PKR.") if __name__ == "__main__": data = pd.read_csv('zameen_data.csv') budget = int(input("Enter your budget (in PKR): ")) while True: city = input("Enter the city (Karachi, Lahore, or Islamabad): ") if city in ["Karachi", "Lahore", "Islamabad"]: break print("Invalid input. Please enter a valid city.") while True: property_type = input("Enter the property type (Flat, House, Penthouse, Farm House, Lower Portion, Upper Portion, or Room): ") if property_type in ["Flat", "House", "Penthouse", "Farm House", "Lower Portion", "Upper Portion", "Room"]: break print("Invalid input. Please enter a valid property type.") predict_location(data, budget, city, property_type)
index.html代码
<!DOCTYPE html> <html> <head> <title>Predicted Location and Price</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <style> .container { width: 80%; margin: 0 auto; } h1 { text-align: center; margin: 20px 0; } label { display: block; margin-bottom: 10px; font-size: 18px; } input[type="number"], select { padding: 10px; font-size: 18px; border-radius: 5px; border: 1px solid #ccc; width: 100%; margin-bottom: 20px; box-sizing: border-box; } button[type="submit"] { background-color: #4CAF50; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 18px; } button[type="submit"]:hover { background-color: #45a049; } .result { margin-top: 30px; font-size: 18px; font-weight: bold; text-align: center; } .map-container { height: 500px; width: 100%; margin-top: 20px; } </style> </head> <body> <div class="container"> <h1>Predicted Location and Price</h1> <form action="/" method="POST"> {% csrf_token %} <label for="budget">Budget (PKR):</label> <input type="number" id="budget" name="budget" required><br> <label for="city">City:</label> <select id="city" name="city"> <option value="Karachi">Karachi</option> <option value="Lahore">Lahore</option> <option value="Islamabad">Islamabad</option> </select><br> <label for="property_type">Property Type:</label> <select id="property_type" name="property_type"> <option value="Flat">Flat</option> <option value="House">House</option> <option value="Penthouse">Penthouse</option> <option value="Farm House">Farm House</option> <option value="Lower Portion">Lower Portion</option> <option value="Upper Portion">Upper Portion</option> <option value="Room">Room</option> </select><br> <label for="period">Period (in months):</label> <input type="number" id="period" name="period" required><br> <button type="submit">Predict Location and Price</button> </form> <div id="result" class="result"></div> <div id="map" class="map-container"></div> </div> <script src="https://api.mapbox.com/mapbox-gl-js/v2.6.0/mapbox-gl.js"></script> <link href="https://api.mapbox.com/mapbox-gl-js/v2.6.0/mapbox-gl.css" rel="stylesheet" /> <script> mapboxgl.accessToken = 'sk.eyJ1IjoibXVzYTc4OSIsImEiOiJjbGY1ZDBzbzgwdHF5M3dvY3F4dGx4a210In0.l-i8jiaS8LWPyXj1ocQiCg'; var map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v11', center: [-122.4194, 37.7749], zoom: 12 }); </script> </body> </html>
问题原因排查
1. Netlify函数适配错误
原Python代码是本地交互式脚本,依赖input()获取命令行输入、webbrowser打开本地地图文件,完全不符合Netlify Functions的运行逻辑:
- Netlify函数必须是HTTP请求处理器,需要接收前端传来的POST/GET请求参数,返回JSON格式的响应,不能用
input()或操作本地文件。 - 需要重构代码为符合Netlify要求的函数格式,比如使用Flask框架封装接口,从请求体中提取
budget、city、property_type、period参数。
2. 部署依赖与资源缺失
- 未声明Python依赖:Netlify部署时需要在项目根目录创建
requirements.txt,列出pandas、scikit-learn、folium等依赖包,否则函数运行会提示模块找不到。 - 数据文件未部署:
zameen_data.csv需要包含在Netlify的部署目录中,否则函数读取文件会报错。
3. 前后端交互逻辑错误
- 表单提交路径错误:Netlify函数的访问路径通常是
/.netlify/functions/[函数文件名],但HTML表单的action设为"/",无法正确触发函数。 - Django模板语法无效:HTML中的
{% csrf_token %}是Django框架的模板标签,纯HTML文件无法解析,会直接显示在页面上,需要删除。 - 地图逻辑脱节:前端用Mapbox初始化地图,但后端用folium生成本地地图文件,两者没有关联。正确逻辑是后端返回预测价格和标注点坐标,前端用Mapbox渲染这些数据。
4. 代码逻辑缺陷
- 预测逻辑不合理:
predict_price函数中固定用[[3,2],[4,3],[3,2],[4,3]]作为输入,根据period取索引,这和周期没有实际关联,需要重新设计预测特征与周期的映射关系。 - 重复添加标记:
predict_location函数的循环中,每次迭代都添加同一个预测位置标记,应该将该代码移到循环外部,避免重复创建。 - 空数据未处理:如果
filtered_data为空(没有符合条件的房产),filtered_data.iloc[0]会抛出索引越界错误,需要添加判断逻辑处理空数据场景。
内容的提问来源于stack exchange,提问作者Musa Mazhar
相关产品推荐
相关产品推荐

