Django视图间传值方法及Fitbit OAuth2授权后令牌获取问询
Fitbit OAuth2.0 后续流程 + Django 视图间传数据指南
我之前刚好做过Django对接Fitbit的项目,这两个问题我太熟了,给你梳理清楚:
一、Fitbit OAuth2.0 授权码换令牌及后续流程
你已经拿到授权码了,接下来就是用这个code去换访问令牌,完整流程是这样的:
1. 先在Django配置里存好Fitbit参数
先把你的Fitbit密钥信息放到settings.py里,方便后续调用:
# settings.py FITBIT_CLIENT_ID = '你的Fitbit Client ID' FITBIT_CLIENT_SECRET = '你的Fitbit Client Secret' FITBIT_REDIRECT_URI = 'https://localhost:8000/你的回调路径' # 和授权链接里的完全一致
2. 构造令牌请求并获取令牌
Fitbit的令牌端点是https://api.fitbit.com/oauth2/token,需要发送POST请求,核心要求如下:
- 必须参数:
grant_type=authorization_code、你的授权码code、重定向URLredirect_uri、client_id - 认证方式:用Basic Auth,把
{client_id}:{client_secret}做Base64编码后放在请求头,或者直接用requests库的auth参数自动处理
Django视图实现示例
import requests from django.shortcuts import redirect, render from django.conf import settings from django.contrib import messages def fitbit_callback(request): # 提取授权码 code = request.GET.get('code') if not code: messages.error(request, '未获取到Fitbit授权码') return redirect('home') # 构造令牌请求 token_url = "https://api.fitbit.com/oauth2/token" payload = { 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': settings.FITBIT_REDIRECT_URI, 'client_id': settings.FITBIT_CLIENT_ID, } # 自动处理Basic Auth认证 auth = (settings.FITBIT_CLIENT_ID, settings.FITBIT_CLIENT_SECRET) response = requests.post(token_url, data=payload, auth=auth) if response.status_code != 200: error_msg = response.json().get('errors', [{}])[0].get('message', '未知错误') messages.error(request, f'获取令牌失败:{error_msg}') return redirect('home') # 解析令牌数据 token_data = response.json() access_token = token_data['access_token'] refresh_token = token_data['refresh_token'] expires_in = token_data['expires_in'] # 令牌有效期(秒,Fitbit默认8小时) # 存储令牌(关键!) # 方式1:存在用户Session(适合临时测试,会话结束失效) request.session['fitbit_access_token'] = access_token request.session['fitbit_refresh_token'] = refresh_token # 方式2:存在用户关联模型(生产环境推荐,需先给User模型加OneToOne关联的FitbitProfile) # request.user.fitbit_profile.access_token = access_token # request.user.fitbit_profile.refresh_token = refresh_token # request.user.fitbit_profile.save() # 现在可以用access_token调用Fitbit API了,比如获取用户今日步数 api_url = "https://api.fitbit.com/1/user/-/activities/steps/date/today/1d.json" headers = {'Authorization': f'Bearer {access_token}'} api_response = requests.get(api_url, headers=headers) if api_response.status_code == 200: steps = api_response.json()['activities-steps'][0]['value'] messages.success(request, f'授权成功!今日步数:{steps}') return redirect('fitbit_dashboard') messages.warning(request, '授权成功但暂时无法获取数据') return redirect('fitbit_dashboard')
3. 令牌过期后的刷新流程
当access_token过期后,用refresh_token换全新令牌:
def refresh_fitbit_token(request): refresh_token = request.session.get('fitbit_refresh_token') if not refresh_token: return redirect('fitbit_auth') token_url = "https://api.fitbit.com/oauth2/token" payload = { 'grant_type': 'refresh_token', 'refresh_token': refresh_token, 'client_id': settings.FITBIT_CLIENT_ID, } auth = (settings.FITBIT_CLIENT_ID, settings.FITBIT_CLIENT_SECRET) response = requests.post(token_url, data=payload, auth=auth) if response.status_code == 200: new_token_data = response.json() # 更新存储的令牌 request.session['fitbit_access_token'] = new_token_data['access_token'] # 注意:Fitbit可能返回新的refresh_token,记得一起更新 if 'refresh_token' in new_token_data: request.session['fitbit_refresh_token'] = new_token_data['refresh_token'] return True return False
二、Django视图间传递数据的正确方式
根据不同场景选对应的方法:
1. Session存储(推荐敏感/大量数据)
适合传递用户专属的敏感数据(比如上面的Fitbit令牌),会话有效期内都能访问:
# 源视图存数据 def source_view(request): request.session['user_preference'] = {'theme': 'dark', 'notifications': True} return redirect('target_view') # 目标视图取数据 def target_view(request): pref = request.session.get('user_preference') if pref: # 使用后建议删除,避免冗余 del request.session['user_preference'] return render(request, 'target.html', {'pref': pref}) return render(request, 'target.html')
2. Messages框架(推荐提示信息)
专门用来传递操作提示(成功/失败/提醒),模板里可以直接渲染:
from django.contrib import messages def source_view(request): messages.success(request, '数据提交成功!') messages.warning(request, '请尽快完善个人信息') return redirect('target_view') # 模板(比如base.html)里添加渲染代码 {% if messages %} <div class="messages"> {% for message in messages %} <div class="alert alert-{{ message.tags }}">{{ message }}</div> {% endfor %} </div> {% endif %}
3. URL参数(适合少量非敏感数据)
传递简单的ID、状态码等非敏感数据,直接拼在重定向URL里:
# 源视图 def source_view(request): order_id = 1001 # 用reverse生成URL更规范 from django.urls import reverse return redirect(reverse('order_detail', kwargs={'order_id': order_id})) # urls.py配置 path('orders/<int:order_id>/', order_detail_view, name='order_detail') # 目标视图 def order_detail_view(request, order_id): # 使用order_id查询订单 return render(request, 'order_detail.html', {'order_id': order_id})
4. 表单POST传递(适合提交后跳转)
如果是表单提交后跳转到处理视图,直接在POST请求里传递数据,但一般建议先处理数据,再用Session/Messages传递结果,避免重复提交。
内容的提问来源于stack exchange,提问作者Henry La
相关产品推荐
相关产品推荐

