使用Django Forms调用API遇阻,终端脚本可正常运行求助
解决Django Form调用Nutritionix API的前端提交问题
嘿,我来帮你搞定这个问题!从你说的情况来看,终端硬编码的脚本能成功调用API,但用Django表单提交就不行,大概率是请求方式不对、前端数据传递有误或者Django视图处理逻辑有漏洞。咱们一步步拆解排查:
先修正你终端脚本里的小问题
你原来的脚本里字典有重复的query键,而且用了body传递参数,但Nutritionix的/v2/search/instant接口是GET请求,参数应该放在URL的查询字符串里,不是请求体。修正后的终端脚本应该是这样:
import requests import json url = "https://trackapi.nutritionix.com/v2/search/instant" headers = { 'x-app-id': "ff0ccea8", 'x-app-key': "605660a17994344157a78f518a111eda" } params = {'query': "apple"} # 用params传递GET参数 response = requests.get(url, headers=headers, params=params) if response.status_code == 200: print(json.dumps(response.json(), indent=2)) else: print(f"请求失败:{response.status_code}") print(response.text)
Django端的完整实现步骤
1. 定义表单类
先在你的app里创建一个表单,用来接收前端的搜索关键词:
# forms.py from django import forms class FoodSearchForm(forms.Form): query = forms.CharField( label='搜索食物', max_length=100, widget=forms.TextInput(attrs={'placeholder': '比如:apple'}) )
2. 编写视图函数处理表单提交和API调用
视图里要做的事:接收表单数据、验证、调用API、返回结果给前端。注意一定要用GET请求调用Nutritionix API,并且通过后端代理(避免前端跨域问题):
# views.py import requests from django.shortcuts import render from django.conf import settings from .forms import FoodSearchForm def food_search(request): results = None error_msg = None if request.method == 'POST': form = FoodSearchForm(request.POST) if form.is_valid(): query = form.cleaned_data['query'] # 从settings里取密钥(别硬编码在代码里!) headers = { 'x-app-id': settings.NUTRITIONIX_APP_ID, 'x-app-key': settings.NUTRITIONIX_APP_KEY } params = {'query': query} api_url = "https://trackapi.nutritionix.com/v2/search/instant" try: response = requests.get(api_url, headers=headers, params=params) response.raise_for_status() # 抛出HTTP错误 results = response.json() except requests.exceptions.RequestException as e: error_msg = f"API调用失败:{str(e)}" print(error_msg) # 后台打印错误方便排查 else: form = FoodSearchForm() return render(request, 'food_search.html', { 'form': form, 'results': results, 'error_msg': error_msg })
3. 配置settings.py(安全起见)
把API密钥放在settings里,不要直接写在视图里:
# settings.py NUTRITIONIX_APP_ID = "ff0ccea8" NUTRITIONIX_APP_KEY = "605660a17994344157a78f518a111eda"
4. 前端模板(food_search.html)
表单要加{% csrf_token %},不然Django会拒绝POST请求;同时展示返回的结果:
<!-- templates/food_search.html --> <!DOCTYPE html> <html> <head> <title>食物营养搜索</title> </head> <body> <h1>搜索食物营养信息</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">搜索</button> </form> {% if error_msg %} <p style="color: red;">{{ error_msg }}</p> {% endif %} {% if results %} <h2>搜索结果</h2> {% if results.common %} <h3>常见食物</h3> <ul> {% for food in results.common %} <li>{{ food.food_name }} - {{ food.serving_qty }} {{ food.serving_unit }}</li> {% endfor %} </ul> {% endif %} {% if results.branded %} <h3>品牌食物</h3> <ul> {% for food in results.branded %} <li>{{ food.brand_name }} - {{ food.food_name }}</li> {% endfor %} </ul> {% endif %} {% endif %} </body> </html>
常见坑点排查
- 请求方式错误:Nutritionix的这个接口只接受GET请求,别用POST传body,否则会返回400错误。
- CSRF令牌缺失:前端表单必须加
{% csrf_token %},否则Django会返回403 Forbidden。 - 跨域问题:不要让前端直接调用Nutritionix API,浏览器会因为CORS政策阻止跨域请求,必须通过Django后端代理。
- 密钥安全:永远不要把API密钥提交到代码仓库,用settings配置+环境变量是更安全的做法。
- 错误处理:一定要捕获API请求的异常,比如网络错误、HTTP错误,方便排查问题。
内容的提问来源于stack exchange,提问作者Gage
相关产品推荐
相关产品推荐

