Django端点如何兼顾登录与未登录场景实现权限校验及数据获取?
解决方案:单端点同时支持登录/未登录用户访问
不需要创建多个端点,只需调整用户ID的获取逻辑和权限校验逻辑,同时修复原有代码中的潜在bug即可实现需求。
核心问题分析
- 未登录时
http_request.user是AnonymousUser,其id为None,直接赋值会导致后续查询异常; - 原有代码中
affiliated_price_subscriptions的判断逻辑错误:即使没有符合条件的订阅,它也会是空列表而非None,导致权限校验失效; - 未处理
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 (...)
关键调整点
- 用户ID处理:通过
http_request.user.is_authenticated判断用户状态,未登录时user_id设为None,避免空值异常; - 存在性校验:先检查
book_account是否存在,提前返回404错误,防止后续属性访问报错; - 权限逻辑重构:
- 登录用户:校验是否属于目标
book_account的组; - 未登录用户:跳过组校验,仅判断是否有符合状态的待处理订阅;
- 只有两个条件都不满足时,才返回权限错误;
- 登录用户:校验是否属于目标
- 错误消息优化:针对未登录用户返回更准确的提示信息。
内容的提问来源于stack exchange,提问作者vale383
相关产品推荐
相关产品推荐

