saas-market-analysis-dubai/apps/core/exceptions.py
2025-09-17 03:04:22 +05:30

129 lines
4.1 KiB
Python

"""
Custom exception handlers for the API.
"""
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.core.exceptions import ValidationError
from django.db import IntegrityError
import logging
logger = logging.getLogger(__name__)
def custom_exception_handler(exc, context):
"""
Custom exception handler for API responses.
"""
# Call REST framework's default exception handler first
response = exception_handler(exc, context)
if response is not None:
custom_response_data = {
'error': True,
'message': 'An error occurred',
'details': response.data,
'status_code': response.status_code,
}
# Handle specific error types
if isinstance(exc, ValidationError):
custom_response_data['message'] = 'Validation error'
custom_response_data['details'] = exc.message_dict if hasattr(exc, 'message_dict') else str(exc)
elif isinstance(exc, IntegrityError):
custom_response_data['message'] = 'Data integrity error'
custom_response_data['details'] = 'The operation could not be completed due to data constraints'
response.status_code = status.HTTP_400_BAD_REQUEST
elif response.status_code == status.HTTP_401_UNAUTHORIZED:
custom_response_data['message'] = 'Authentication required'
custom_response_data['details'] = 'Please provide valid authentication credentials'
elif response.status_code == status.HTTP_403_FORBIDDEN:
custom_response_data['message'] = 'Access denied'
custom_response_data['details'] = 'You do not have permission to perform this action'
elif response.status_code == status.HTTP_404_NOT_FOUND:
custom_response_data['message'] = 'Resource not found'
custom_response_data['details'] = 'The requested resource could not be found'
elif response.status_code == status.HTTP_429_TOO_MANY_REQUESTS:
custom_response_data['message'] = 'Rate limit exceeded'
custom_response_data['details'] = 'Too many requests. Please try again later.'
elif response.status_code >= 500:
custom_response_data['message'] = 'Internal server error'
custom_response_data['details'] = 'An unexpected error occurred. Please try again later.'
# Log server errors
logger.error(f"Server error: {exc}", exc_info=True)
response.data = custom_response_data
return response
class APIException(Exception):
"""
Base exception for API errors.
"""
status_code = status.HTTP_400_BAD_REQUEST
message = 'An error occurred'
def __init__(self, message=None, status_code=None, details=None):
if message:
self.message = message
if status_code:
self.status_code = status_code
self.details = details or {}
super().__init__(self.message)
class ValidationException(APIException):
"""
Exception for validation errors.
"""
status_code = status.HTTP_400_BAD_REQUEST
message = 'Validation error'
class AuthenticationException(APIException):
"""
Exception for authentication errors.
"""
status_code = status.HTTP_401_UNAUTHORIZED
message = 'Authentication required'
class PermissionException(APIException):
"""
Exception for permission errors.
"""
status_code = status.HTTP_403_FORBIDDEN
message = 'Access denied'
class NotFoundException(APIException):
"""
Exception for not found errors.
"""
status_code = status.HTTP_404_NOT_FOUND
message = 'Resource not found'
class RateLimitException(APIException):
"""
Exception for rate limit errors.
"""
status_code = status.HTTP_429_TOO_MANY_REQUESTS
message = 'Rate limit exceeded'
class BusinessLogicException(APIException):
"""
Exception for business logic errors.
"""
status_code = status.HTTP_422_UNPROCESSABLE_ENTITY
message = 'Business logic error'