Django Ninja第三方API集成:调用外部服务
在现代Web开发中,与第三方服务交互是常见需求。Django Ninja作为基于类型提示的高性能API框架,提供了简洁的方式来实现外部服务集成。本文将从同步和异步两种方式,详细介绍如何在Django Ninja项目中调用第三方API,解决超时处理、错误捕获等关键问题。
同步调用第三方API
同步调用适用于简单场景,可直接使用Python标准库或第三方HTTP客户端。以下是使用requests库调用外部服务的示例:
# someapp/api.py
import requests
from ninja import Router
from pydantic import BaseModel
router = Router()
class WeatherResponse(BaseModel):
city: str
temperature: float
description: str
@router.get("/weather", response=WeatherResponse)
def get_weather(request, city: str):
"""获取指定城市天气信息"""
api_key = "your_api_key"
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
try:
response = requests.get(url, timeout=5)
response.raise_for_status() # 抛出HTTP错误
data = response.json()
return {
"city": data["name"],
"temperature": data["main"]["temp"],
"description": data["weather"][0]["description"]
}
except requests.exceptions.RequestException as e:
return {"error": str(e)}, 503
代码中使用requests.get()发起同步请求,并通过try-except捕获网络异常。响应模型WeatherResponse确保API输出符合类型规范,这是Django Ninja的核心特性之一。
异步调用第三方API
对于高并发场景,异步调用能显著提升性能。Django Ninja原生支持异步视图,配合aiohttp库可实现非阻塞HTTP请求:
# someapp/api.py
import aiohttp
from ninja import Router
from pydantic import BaseModel
router = Router()
class GitHubUser(BaseModel):
login: str
name: str
public_repos: int
@router.get("/github/user", response=GitHubUser)
async def get_github_user(request, username: str):
"""获取GitHub用户信息"""
url = f"https://api.github.com/users/{username}"
async with aiohttp.ClientSession() as session:
try:
async with session.get(url, timeout=10) as response:
response.raise_for_status()
data = await response.json()
return {
"login": data["login"],
"name": data.get("name", "N/A"),
"public_repos": data["public_repos"]
}
except aiohttp.ClientError as e:
return {"error": str(e)}, 503
异步视图通过async def定义,使用aiohttp.ClientSession发起非阻塞请求。这种方式特别适合需要同时调用多个API的场景,避免因等待单个请求而阻塞整个应用。
高级集成模式
1. API调用封装
将第三方API调用封装为独立服务类,可提高代码复用性和可测试性:
# someapp/services.py
import httpx
from typing import Dict, Optional
class APIClient:
def __init__(self, base_url: str, timeout: int = 10):
self.base_url = base_url
self.timeout = timeout
def get(self, endpoint: str, params: Optional[Dict] = None) -> Dict:
"""同步GET请求"""
with httpx.Client(timeout=self.timeout) as client:
response = client.get(f"{self.base_url}/{endpoint}", params=params)
response.raise_for_status()
return response.json()
async def async_get(self, endpoint: str, params: Optional[Dict] = None) -> Dict:
"""异步GET请求"""
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.get(f"{self.base_url}/{endpoint}", params=params)
response.raise_for_status()
return await response.json()
在视图中使用封装的客户端:
# someapp/api.py
from ninja import Router
from .services import APIClient
router = Router()
client = APIClient("https://api.github.com")
@router.get("/github/repos")
async def list_repos(request, username: str):
"""列出用户GitHub仓库"""
data = await client.async_get(f"users/{username}/repos")
return [{"name": repo["name"], "stars": repo["stargazers_count"]} for repo in data]
2. 集成Swagger文档
Django Ninja自动生成OpenAPI文档,可直观展示第三方API集成效果。访问/docs路径即可看到交互式API文档界面:
通过在视图函数中添加文档字符串,可自动生成API说明:
@router.get("/weather", response=WeatherResponse)
def get_weather(request, city: str):
"""
获取城市天气信息
- **city**: 城市名称(如"Beijing")
- 返回当前温度和天气状况
"""
# 实现代码...
文档生成功能由ninja/openapi/views.py提供支持,自动解析类型提示和函数注释,生成符合OpenAPI规范的接口文档。
错误处理与最佳实践
超时控制
第三方API调用必须设置超时,避免长时间阻塞:
# 同步超时设置
response = requests.get(url, timeout=5) # 5秒超时
# 异步超时设置
async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)):
pass
重试机制
使用tenacity库实现失败重试:
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
async def fetch_data(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
response.raise_for_status()
return await response.json()
安全存储API密钥
敏感信息应使用Django设置存储,避免硬编码:
# settings.py
THIRD_PARTY_APIS = {
"WEATHER_API_KEY": os.environ.get("WEATHER_API_KEY"),
"GITHUB_TOKEN": os.environ.get("GITHUB_TOKEN")
}
# 在视图中使用
from django.conf import settings
api_key = settings.THIRD_PARTY_APIS["WEATHER_API_KEY"]
项目结构与代码组织
推荐的第三方API集成项目结构:
someapp/
├── api.py # API视图定义
├── services.py # 第三方服务客户端
├── schemas.py # 请求/响应模型
├── exceptions.py # 自定义异常
└── tests.py # 测试用例
这种结构将数据模型、业务逻辑和API接口分离,符合Django应用的最佳实践。相关代码可参考测试项目中的demo_project/someapp/api.py实现。
总结
Django Ninja提供了灵活的方式集成第三方API,无论是简单的同步调用还是高性能的异步请求,都能通过简洁的代码实现。核心要点包括:
- 使用类型提示和Pydantic模型确保数据安全
- 优先采用异步调用提升并发性能
- 封装API客户端提高代码复用性
- 完善错误处理和超时控制
- 利用自动生成的OpenAPI文档简化测试
通过本文介绍的方法,开发者可以高效地将外部服务集成到Django Ninja项目中,构建功能完善的API应用。更多高级用法可参考官方文档docs/guides/async-support.md和docs/reference/api.md。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




