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

Django如何像抛出Http404一样抛出Http401与Http403异常(非返回响应)

Hey there! Let's work through this Django API authorization issue you're dealing with. The good news is your approach of using exceptions (like get_object_or_404) is totally valid—you just need to align with how Django handles HTTP exceptions under the hood.

First, Clarify Django's Built-in Exceptions

Django has native support for common HTTP error exceptions, but not all status codes have pre-defined classes out of the box:

  • Http404 (from django.http) works because Django's default exception handler automatically catches it and returns a 404 response.
  • For 403 Forbidden, Django uses PermissionDenied (from django.core.exceptions)—this is the built-in exception you should use instead of a custom Http403 class, since Django knows how to handle it natively.
  • There's no built-in Http401 exception, but we can define one and configure Django to handle it properly.

Fix Your Authorization Function

Let's adjust your code to use the right exceptions, plus align the status code logic with standard HTTP practices (401 = missing credentials, 403 = invalid credentials):

from django.core.exceptions import PermissionDenied

# Define a custom exception for 401 Unauthorized
class Http401(Exception):
    pass

def _check_driver_authorization(request):
    auth_token = request.headers.get('authorization')
    
    # No authorization header provided → 401 Unauthorized
    if not auth_token:
        raise Http401("Authorization header is required to access this resource")
    
    # Token exists but doesn't match any driver → 403 Forbidden
    driver = Driver.objects.filter(access_token=auth_token).first()
    if not driver:
        raise PermissionDenied("Invalid or expired access token")
    
    # Attach the valid driver to the request for use in views
    request.driver = driver

Configure Django to Handle the Custom Http401 Exception

Since Http401 is custom, we need to tell Django how to convert it into a proper HTTP response. Add this to your project's urls.py:

from django.http import HttpResponseUnauthorized

def custom_401_handler(request, exception):
    # Return a JSON response (ideal for APIs) with the error message
    return HttpResponseUnauthorized({"error": str(exception)})

# Register the handler for 401 errors
handler401 = custom_401_handler

Why Your Original Custom Http403 Failed

Django's default exception handler only recognizes a specific set of built-in exceptions (like Http404 and PermissionDenied). When you threw a custom Http403 exception, Django didn't know how to map it to a 403 response—hence the issues you saw. Using PermissionDenied eliminates this problem entirely.

Bonus: If You're Using Django REST Framework (DRF)

If you're building APIs with DRF, you can simplify this even more by using DRF's built-in authentication/permission classes. DRF automatically handles 401/403 responses for you, so you don't have to write custom exception handlers:

from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response

class DriverAPIView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    
    def get(self, request):
        # Your view logic here—DRF already handled auth checks
        return Response({"message": "Authorized driver access"})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:43:05