You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+React前后端架构下带查询参数调用第三方API的正确实现方式

方案总览

你当前的实现存在不必要的请求冗余:后端从OpenWeatherMap拉取到数据后,无需额外存储后再等待前端发起GET请求拉取,完全可以在接收前端POST请求的同一次HTTP响应中直接返回处理好的天气数据,整个链路仅需2次HTTP调用(前端→你的后端、你的后端→OpenWeatherMap),没有多余往返。

具体实现步骤

Django后端侧调整

你已经完成了后端请求OpenWeatherMap的核心逻辑,只需要调整视图的响应逻辑即可,无需额外新增存储、二次接口:

  • 固定天气查询接口路径,例如/api/weather/,仅允许POST方法请求
  • 视图入口先从POST请求体中解析前端传入的城市名参数,做基础非空校验
  • 从服务端环境变量读取OpenWeatherMap密钥(禁止硬编码到代码中),携带城市名向第三方接口发起请求,注意设置请求超时时间
  • 拿到第三方返回结果后做字段裁剪,只保留前端需要展示的核心字段,不要透传第三方返回的全量冗余数据
  • 异常场景(参数为空、城市不存在、第三方接口请求失败)统一返回对应错误码和可读提示,正常场景直接在当前请求的响应中返回处理好的天气JSON数据
  • 安装django-cors-headers配置跨域规则,允许前端服务地址的请求,避免本地调试时被浏览器拦截

参考视图代码(基于Django REST Framework实现):

# views.py
import os
import requests
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

OWM_API_KEY = os.getenv("OWM_API_KEY") # 从环境变量读取密钥,不要硬编码

class WeatherQueryView(APIView):
    def post(self, request):
        city_name = request.data.get("city", "").strip()
        if not city_name:
            return Response({"error": "城市名不能为空"}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            owm_resp = requests.get(
                "https://api.openweathermap.org/data/2.5/weather",
                params={
                    "q": city_name,
                    "appid": OWM_API_KEY,
                    "units": "metric",
                    "lang": "zh_cn"
                },
                timeout=10
            )
            owm_resp.raise_for_status()
            raw_data = owm_resp.json()
            # 裁剪前端需要的字段
            processed_data = {
                "city": raw_data["name"],
                "temp": raw_data["main"]["temp"],
                "weather_desc": raw_data["weather"][0]["description"],
                "humidity": raw_data["main"]["humidity"],
                "wind_speed": raw_data["wind"]["speed"]
            }
            return Response(processed_data, status=status.HTTP_200_OK)
        except requests.exceptions.RequestException:
            return Response({"error": "查询失败,请检查城市名或稍后重试"}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

配置路由时将上述视图绑定到/api/weather/路径即可。

React前端侧调整

前端不需要拆分POST提交、GET拉取两步逻辑,单次请求即可完成全流程:

  • 通过受控组件存储用户输入的城市名,搭配输入框、查询按钮组成基础表单
  • 触发查询时先开启loading状态,避免用户重复点击,同时清空历史结果和错误提示
  • 用axios向自己的Django接口发POST请求,请求体携带用户输入的城市名
  • 请求成功后将返回的天气数据存入组件state,渲染到页面;请求失败时展示后端返回的错误提示
  • 请求完成后无论成功失败都关闭loading状态

参考组件代码:

// WeatherQuery.jsx
import { useState } from 'react';
import axios from 'axios';

export default function WeatherQuery() {
  const [city, setCity] = useState('');
  const [weatherInfo, setWeatherInfo] = useState(null);
  const [loading, setLoading] = useState(false);
  const [errorMsg, setErrorMsg] = useState('');

  const handleSearch = async (e) => {
    e.preventDefault();
    const targetCity = city.trim();
    if (!targetCity) {
      setErrorMsg('请输入要查询的城市名');
      return;
    }
    setLoading(true);
    setErrorMsg('');
    setWeatherInfo(null);
    try {
      const res = await axios.post('/api/weather/', { city: targetCity });
      setWeatherInfo(res.data);
    } catch (err) {
      setErrorMsg(err.response?.data?.error || '网络异常,请稍后重试');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={city}
          onChange={(e) => setCity(e.target.value)}
          placeholder="输入城市名查询天气"
        />
        <button type="submit" disabled={loading}>
          {loading ? '查询中...' : '查询天气'}
        </button>
      </form>
      {errorMsg && <p style={{color: 'red'}}>*{errorMsg}</p>}
      {weatherInfo && (
        <div>
          <h3>{weatherInfo.city} 实时天气</h3>
          <p>天气状况:{weatherInfo.weather_desc}</p>
          <p>当前温度:{weatherInfo.temp}℃</p>
          <p>相对湿度:{weatherInfo.humidity}%</p>
          <p>风速:{weatherInfo.wind_speed}m/s</p>
        </div>
      )}
    </div>
  );
}

本地调试时可以在React配置中添加代理规则,将/api开头的请求转发到Django默认运行的http://localhost:8000地址,省去跨域配置的麻烦。

注意事项
  • OpenWeatherMap密钥必须存在服务端环境变量中,禁止提交到代码仓库,也禁止在前端代码中出现
  • 后端请求第三方接口必须设置合理的超时时间,避免第三方服务异常拖垮自身服务
  • 可以给天气查询接口添加简单的频率限制,避免被恶意刷量消耗第三方API的调用额度
  • 生产环境建议将前端打包后的静态文件交由Nginx或Django托管,不存在跨域问题

内容的提问来源于stack exchange,提问作者Prajwal Iyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:18:15