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

Django技术问题:如何根据微软账户类型获取对应模型的令牌?

问题:根据用户账户类型正确匹配Microsoft Graph令牌模型

问题背景

我在Django项目中集成了Microsoft Graph API,登录成功后将微软企业账户的access_token和refresh_token存储至ModelA,个人账户的令牌存储至ModelB。需求是根据用户的账户类型(企业/个人),调用对应模型的令牌——企业账户使用ModelA的令牌,个人账户使用ModelB的令牌。

但当前实现逻辑存在问题:当两个模型中都存在令牌数据时,总是优先调用先查询的ModelA,无法根据实际用户类型切换到对应模型;仅当其中一个模型无数据时才能正常工作。

模型定义

ModelA(企业账户令牌存储)

class ModelA(models.Model):
    active = models.BooleanField(null=True, blank=True)
    for_user = models.ForeignKey(ModelX, null=True, blank=True, on_delete=models.CASCADE)
    for_firm = models.ForeignKey(ModelMain, related_name="microsoft_for_firm", null=True, blank=True, on_delete=models.CASCADE)
    access_token = models.TextField(null=True, blank=True)
    refresh_token = models.TextField(null=True, blank=True)

ModelB(个人账户令牌存储)

class ModelB(models.Model):
    active = models.BooleanField(null=True, blank=True)
    for_user = models.ForeignKey(ModelX, null=True, blank=True, on_delete=models.CASCADE)
    for_firm = models.ForeignKey(ModelMain, related_name="microsoft_for_personal", null=True, blank=True, on_delete=models.CASCADE)
    access_token = models.TextField(null=True, blank=True)
    refresh_token = models.TextField(null=True, blank=True)

当前错误实现代码

refresh_token = None
access_token = None
userprofile = None
try:
    profile = ModelF.objects.get(user=request.user, account_type='Attorney')
    userprofile = ModelMain.objects.get(attorneyprofile=profile)
except:
    userprofile = ModelX.objects.get(user=request.user, account_type='AttorneyStaff')
    userprofile = userprofile.created_by
org_refresh_token = ModelA.objects.filter(for_firm=userprofile, refresh_token__startswith='0.AU').first()
if org_refresh_token:
    access_token = org_refresh_token.access_token
    print("\n Access Token :", access_token)
    user_type = get_user_type(access_token)
    print("\n User type in get refresh token :", user_type)
    if user_type == 'Member' and org_refresh_token.refresh_token.startswith("0.AU"):
        print("\n Member found \n")
        refresh_token = org_refresh_token.refresh_token
        print("\n REFRESH TOKEN Organisation :", refresh_token)
    else:
        per_refresh_token = ModelB.objects.filter(for_firm=userprofile, refresh_token__startswith='M.R3').first()
        if per_refresh_token:
            refresh_token = per_refresh_token.refresh_token
            print("\n REFRESH TOKEN Personal:", refresh_token)
else:
    per_refresh_token = ModelB.objects.filter(for_firm=userprofile, refresh_token__startswith='M.R3').first()
    refresh_token = per_refresh_token.refresh_token
    print("\n REFRESH TOKEN Organisation:", refresh_token)

问题分析

当前代码的核心错误是逻辑顺序倒置:它先查询企业令牌(ModelA),再根据令牌的user_type决定是否切换到个人令牌(ModelB),而非先明确用户的目标账户类型,再定向查询对应模型的令牌。这种逻辑导致当两个模型都有数据时,始终优先使用ModelA,完全忽略用户的实际账户类型需求。

修复方案

我们需要先明确用户的目标账户类型(企业/个人),再直接到对应模型查询有效令牌。以下是调整后的实现:

1. 定义获取用户目标账户类型的函数

根据你的业务逻辑实现,比如从用户的profile、session或系统设置中读取用户选择的账户类型:

def get_target_microsoft_account_type(request):
    # 示例:从用户session获取临时选择的账户类型,默认企业
    return request.session.get('selected_microsoft_account', 'enterprise')
    # 若用户profile有固定设置,可替换为:
    # return request.user.microsoft_profile.account_type

2. 调整令牌获取逻辑

refresh_token = None
access_token = None
userprofile = None

# 保留原逻辑:获取用户对应的企业/机构信息
try:
    profile = ModelF.objects.get(user=request.user, account_type='Attorney')
    userprofile = ModelMain.objects.get(attorneyprofile=profile)
except ModelF.DoesNotExist:
    userprofile = ModelX.objects.get(user=request.user, account_type='AttorneyStaff')
    userprofile = userprofile.created_by

# 第一步:明确用户需要的账户类型
target_account_type = get_target_microsoft_account_type(request)

# 第二步:根据目标类型定向查询对应模型的令牌
if target_account_type == 'enterprise':
    # 企业账户:查询ModelA,匹配企业令牌格式
    token_obj = ModelA.objects.filter(for_firm=userprofile, refresh_token__startswith='0.AU').first()
    if token_obj:
        access_token = token_obj.access_token
        refresh_token = token_obj.refresh_token
        print("\n 已获取企业账户令牌")
else:
    # 个人账户:查询ModelB,匹配个人令牌格式
    token_obj = ModelB.objects.filter(for_firm=userprofile, refresh_token__startswith='M.R3').first()
    if token_obj:
        access_token = token_obj.access_token
        refresh_token = token_obj.refresh_token
        print("\n 已获取个人账户令牌")

# 容错处理:未找到对应类型的令牌
if not refresh_token:
    print(f"\n 未找到{target_account_type}类型的有效令牌,请绑定对应微软账户")

3. 可选:基于令牌类型的校验(若需确保令牌类型与目标一致)

如果需要验证令牌的实际类型是否符合目标(防止令牌格式错误),可以添加校验逻辑:

def get_valid_token_by_type(userprofile, target_type):
    if target_type == 'enterprise':
        token_obj = ModelA.objects.filter(for_firm=userprofile, refresh_token__startswith='0.AU').first()
        if token_obj:
            # 验证令牌的用户类型是否为企业成员
            user_type = get_user_type(token_obj.access_token)
            if user_type == 'Member':
                return token_obj.access_token, token_obj.refresh_token
    else:
        token_obj = ModelB.objects.filter(for_firm=userprofile, refresh_token__startswith='M.R3').first()
        if token_obj:
            # 可添加个人账户令牌的校验逻辑
            return token_obj.access_token, token_obj.refresh_token
    return None, None

# 使用方式
access_token, refresh_token = get_valid_token_by_type(userprofile, target_account_type)

关键优化点

  • 逻辑前置:先确定用户的账户类型需求,再定向查询对应模型,彻底解决优先使用某一模型的问题。
  • 逻辑解耦:将账户类型判断与令牌查询分离,代码更清晰,便于后续维护。
  • 容错增强:添加无令牌时的提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:10:06