Coverage for utilities/error_handlers.py: 44%
35 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1import platform
2import sys
4from django.conf import settings
5from django.contrib import messages
6from django.db.models import ProtectedError, RestrictedError
7from django.http import JsonResponse
8from django.utils.html import escape
9from django.utils.safestring import mark_safe
10from django.utils.translation import gettext_lazy as _
11from rest_framework import status
13__all__ = (
14 'handle_protectederror',
15 'handle_rest_api_exception',
16)
19def handle_protectederror(obj_list, request, e):
20 """
21 Generate a user-friendly error message in response to a ProtectedError or RestrictedError exception.
22 """
23 if type(e) is ProtectedError:
24 protected_objects = list(e.protected_objects)
25 elif type(e) is RestrictedError:
26 protected_objects = list(e.restricted_objects)
27 else:
28 raise e
30 # Formulate the error message
31 err_message = _('Unable to delete <strong>{objects}</strong>. {count} dependent objects were found: ').format(
32 objects=', '.join(escape(obj) for obj in obj_list),
33 count=len(protected_objects) if len(protected_objects) <= 50 else _('More than 50'),
34 )
36 # Append dependent objects to error message
37 dependent_objects = []
38 for dependent in protected_objects[:50]:
39 if hasattr(dependent, 'get_absolute_url'):
40 dependent_objects.append(f'<a href="{dependent.get_absolute_url()}">{escape(dependent)}</a>')
41 else:
42 dependent_objects.append(escape(str(dependent)))
43 err_message += ', '.join(dependent_objects)
45 messages.error(request, mark_safe(err_message))
48def handle_rest_api_exception(request, *args, **kwargs):
49 """
50 Handle exceptions and return a useful error message for REST API requests.
51 """
52 if 'error' in kwargs: 52 ↛ 53line 52 didn't jump to line 53 because the condition on line 52 was never true
53 error_message = str(kwargs['error'])
54 type_, __ = sys.exc_info()[:2]
55 exception_name = type_.__name__ if type_ else 'Exception'
56 else:
57 type_, error = sys.exc_info()[:2]
58 error_message = str(error)
59 exception_name = type_.__name__
60 data = {
61 'error': error_message,
62 'exception': exception_name,
63 'netbox_version': settings.RELEASE.full_version,
64 'python_version': platform.python_version(),
65 }
66 return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)