如何在Django应用中通过GitHub API获取指定用户指定月份的Pull Requests?
在Django中通过GitHub API获取指定用户特定月份的Pull Requests
嘿,我来帮你搞定这个需求!要在Django应用里拉取指定用户某月份创建的PR,咱们得先理清GitHub API的正确用法,再一步步实现代码逻辑。
第一步:搞懂GitHub API的正确姿势
你给出的示例用了/issues端点,但其实GitHub的Pull Requests是特殊类型的Issue,用搜索API或者专门的/pulls端点会更精准。这里推荐用搜索API,因为它支持灵活的时间范围和多条件筛选。
比如要获取myrepo/example仓库中,person_name在2018年1月创建的所有PR,正确的API查询逻辑是:
GET /search/issues?q=repo:myrepo/example+is:pr+creator:person_name+created:2018-01-01..2018-01-31
参数说明:
repo:myrepo/example:锁定目标仓库is:pr:只筛选Pull Requests(排除普通Issue)creator:person_name:指定PR的创建者created:YYYY-MM-DD..YYYY-MM-DD:限定创建时间的闭区间范围
⚠️ 重要提醒:一定要用**个人访问令牌(PAT)**认证请求!未认证请求每小时只有60次限额,用PAT能提升到5000次。创建PAT时,只需给repo(私有仓库)或public_repo(公开仓库)权限即可。
第二步:在Django中实现请求逻辑
首先确保安装了requests库(用来发送HTTP请求):
pip install requests
接下来写一个工具函数,封装API请求和分页处理(GitHub API结果默认分页,最多每页100条):
import requests from datetime import datetime, timedelta from django.conf import settings def get_user_monthly_prs(repo_owner, repo_name, username, year, month): # 自动计算当月的起始和结束日期 start_date = f"{year}-{month:02d}-01" # 计算当月最后一天,避免手动处理不同月份天数的麻烦 next_month_first_day = datetime(year, month, 1) + timedelta(days=32) end_date = next_month_first_day.replace(day=1) - timedelta(days=1) end_date_str = end_date.strftime("%Y-%m-%d") # 构造API请求参数 api_url = "https://api.github.com/search/issues" query_params = { "q": f"repo:{repo_owner}/{repo_name}+is:pr+creator:{username}+created:{start_date}..{end_date_str}", "per_page": 100, # 每页最多返回100条,减少分页请求次数 } # 认证头,把你的PAT配置在Django的settings.py里 request_headers = { "Authorization": f"token {settings.GITHUB_PAT}", "Accept": "application/vnd.github.v3+json" } all_prs = [] current_url = api_url # 处理分页,直到没有下一页 while current_url: response = requests.get(current_url, params=query_params, headers=request_headers) # 主动抛出HTTP错误,方便后续处理 response.raise_for_status() response_data = response.json() all_prs.extend(response_data["items"]) # 解析Link头,获取下一页链接 link_header = response.headers.get("Link") current_url = None if link_header: for link in link_header.split(", "): if 'rel="next"' in link: current_url = link.split("; ")[0].strip("<>") query_params = {} # 下一页链接已包含所有参数,无需重复传递 return all_prs
第三步:在Django视图中调用工具函数
你可以写一个视图来返回处理后的PR数据,比如以JSON格式返回:
from django.http import JsonResponse from .utils import get_user_monthly_prs # 假设工具函数在utils.py里 def user_monthly_prs(request): # 这里可以从请求参数中动态获取仓库、用户、年月,示例先写死 repo_owner = "myrepo" repo_name = "example" username = "person_name" target_year = 2018 target_month = 1 try: prs = get_user_monthly_prs(repo_owner, repo_name, username, target_year, target_month) # 提取需要的字段简化返回结果 simplified_prs = [ { "title": pr["title"], "pr_url": pr["html_url"], "created_time": pr["created_at"], "state": pr["state"] } for pr in prs ] return JsonResponse({"pull_requests": simplified_prs}) except requests.exceptions.RequestException as e: return JsonResponse({"error": str(e)}, status=500)
额外注意事项
- 速率限制处理:GitHub API会返回
X-RateLimit-Remaining和X-RateLimit-Reset响应头,你可以在代码中添加逻辑,当剩余请求次数不足时等待重置时间。 - 错误捕获:务必处理网络错误、认证失败、仓库不存在等异常情况,避免应用崩溃。
- PAT安全:不要把PAT硬编码在代码里,放在Django的
settings.py中,并且确保敏感配置不提交到版本库。
内容的提问来源于stack exchange,提问作者Awaish Kumar
相关产品推荐
相关产品推荐

