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

Django端点如何兼顾登录与未登录场景实现权限校验及数据获取?

解决方案:单端点同时支持登录/未登录用户访问

不需要创建多个端点,只需调整用户ID的获取逻辑和权限校验逻辑,同时修复原有代码中的潜在bug即可实现需求。

核心问题分析

  1. 未登录时http_request.user是AnonymousUser,其id为None,直接赋值会导致后续查询异常;
  2. 原有代码中affiliated_price_subscriptions的判断逻辑错误:即使没有符合条件的订阅,它也会是空列表而非None,导致权限校验失效;
  3. 未处理book_account不存在的情况,会引发属性访问错误。

修改后的代码示例

def get(http_request: HttpRequest, id: str):
    book_account_id = UUID(id)
    # 区分登录/未登录用户,正确获取user_id
    user_id = http_request.user.id if http_request.user.is_authenticated else None
    affiliated_price_subscriptions = []

    response = BookAccountService.filter(
        id=book_account_id
    ).prefetch_related(
        Prefetch(
            'subscription_set',
            queryset=SubscriptionRepository.filter(
                active=True
            ).prefetch_related(
                Prefetch(
                    'pricesubscription_set',
                    queryset=PriceSubscriptionRepository.filter(
                        Q(status=PriceSubscription.PriceSubscriptionStatus.PENDING) |
                        Q(status=PriceSubscription.PriceSubscriptionStatus.REQUIRES_PAYMENT)
                    ),
                    to_attr='price_subscriptions'
                )
            ),
            to_attr='subscriptions'
        )
    ).first()

    # 先判断book_account是否存在
    if not response:
        return RestResponse(
            status=status.HTTP_404_NOT_FOUND,
            data=Response(
                code=25,
                error=True,
                messages=[f"Book account with ID {book_account_id} not found."],
                data=None,
            ).to_dict(),
        )

    # 提取符合条件的price-subscription
    affiliated_price_subscriptions = list(chain.from_iterable(
        subscription.price_subscriptions for subscription in response.subscriptions
    ))

    # 权限校验逻辑拆分
    has_group_access = False
    if http_request.user.is_authenticated:
        # 仅登录用户需校验组归属
        has_group_access = PersonGroupService.exists(
            person__user_id=user_id,
            group__bookaccount__id=book_account_id
        )
    # 判断是否有符合状态的待处理订阅
    has_pending_subscription = len(affiliated_price_subscriptions) > 0

    # 两个条件都不满足时返回权限错误
    if not has_group_access and not has_pending_subscription:
        error_msg = f"User with ID {user_id} does not have access to book account with ID {book_account_id}." if user_id else "Unauthorized access to book account."
        return RestResponse(
            status=status.HTTP_200_OK,
            data=Response(
                code=24,
                error=True,
                messages=[error_msg],
                data=None,
            ).to_dict(),
        )

    # 返回正常数据
    return (...)

关键调整点

  1. 用户ID处理:通过http_request.user.is_authenticated判断用户状态,未登录时user_id设为None,避免空值异常;
  2. 存在性校验:先检查book_account是否存在,提前返回404错误,防止后续属性访问报错;
  3. 权限逻辑重构:
    • 登录用户:校验是否属于目标book_account的组;
    • 未登录用户:跳过组校验,仅判断是否有符合状态的待处理订阅;
    • 只有两个条件都不满足时,才返回权限错误;
  4. 错误消息优化:针对未登录用户返回更准确的提示信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:52:25