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

Django视图调用Google Sheets API遇OAuth2 400重定向URI不匹配错误

解决Django对接Google Sheets API的redirect_uri_mismatch问题

这个问题我之前踩过坑,核心原因其实是你用的Google官方快速入门代码里的run_local_server()方法,根本不是为Django这类Web框架设计的——它会偷偷启动一个临时的本地HTTP服务器来处理OAuth2的授权回调,默认情况下会随机挑一个可用的端口(就是你看到的65262这种),哪怕你设了port=0,系统还是会自动分配随机端口,这和你Django服务用的8000端口完全是两个独立的东西,自然就和API控制台里设置的回调URI不匹配了。

解决步骤

1. 调整Google API控制台的回调URI

先去Google API控制台,把你的授权回调URI改成Django服务的回调地址,比如:
http://127.0.0.1:8000/google-oauth-callback/
(如果是生产环境,记得换成你域名对应的HTTPS地址)

2. 修改Django视图代码,抛弃临时服务器

不要用run_local_server()了,手动处理OAuth2的授权流程,让回调直接指向你的Django视图:

第一步:添加回调URL路由

在你的urls.py里加一条路由:

path('google-oauth-callback/', views.google_oauth_callback, name='google_oauth_callback'),

第二步:修改授权视图和回调视图

把原来依赖run_local_server()的代码替换成下面的逻辑:

from google_auth_oauthlib.flow import Flow
from django.http import HttpResponseRedirect, HttpResponse
from django.conf import settings

# Google Sheets API的权限范围,根据你的需求调整
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']

def sheets_auth_init(request):
    # 构建OAuth2流程,指定回调URI为我们刚加的Django路由
    flow = Flow.from_client_secrets_file(
        'credentials.json',  # 你的Google凭证文件路径
        scopes=SCOPES,
        redirect_uri='http://127.0.0.1:8000/google-oauth-callback/'
    )
    # 生成授权URL,同时开启离线访问模式(获取refresh_token)
    authorization_url, state = flow.authorization_url(
        access_type='offline',
        include_granted_scopes='true'
    )
    # 把state存到session里,回调时用来验证请求合法性
    request.session['oauth_state'] = state
    # 重定向到Google的授权页面
    return HttpResponseRedirect(authorization_url)

def google_oauth_callback(request):
    # 从session取出之前存的state
    saved_state = request.session.get('oauth_state')
    if not saved_state:
        return HttpResponse("授权请求无效,请重新发起", status=400)
    
    # 重新构建flow,传入state和回调URI
    flow = Flow.from_client_secrets_file(
        'credentials.json',
        scopes=SCOPES,
        state=saved_state,
        redirect_uri='http://127.0.0.1:8000/google-oauth-callback/'
    )
    # 用授权码交换访问令牌
    flow.fetch_token(authorization_response=request.build_absolute_uri())
    
    # 拿到凭证后,你可以把它存在session、数据库或者缓存里
    creds = flow.credentials
    request.session['sheets_creds'] = {
        'token': creds.token,
        'refresh_token': creds.refresh_token,
        'token_uri': creds.token_uri,
        'client_id': creds.client_id,
        'client_secret': creds.client_secret,
        'scopes': creds.scopes
    }
    
    # 这里可以跳转到你的业务页面,或者直接返回成功提示
    return HttpResponse("授权成功!现在可以访问Google Sheets数据了")

3. 后续使用凭证调用API

之后你需要调用Google Sheets API的时候,就从session里取出凭证,重新构建Credentials对象:

from google.oauth2.credentials import Credentials

def get_sheets_data(request):
    creds_data = request.session.get('sheets_creds')
    if not creds_data:
        return HttpResponseRedirect('/sheets-auth-init/')
    
    creds = Credentials.from_authorized_user_info(creds_data)
    # 这里就可以用creds调用Google Sheets API了,比如:
    # service = build('sheets', 'v4', credentials=creds)
    # ......

额外注意事项

  • 开发环境下用127.0.0.1或者localhost都可以,但要确保API控制台里的回调URI和代码里的完全一致(包括端口和路径)
  • 生产环境一定要用HTTPS,Google OAuth2不允许非HTTPS的回调(除了本地开发的127.0.0.1/localhost)
  • credentials.json要妥善保存,不要提交到Git等版本控制系统里,可以用Django的settings来管理路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:57:54