error_handlers.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import platform
  2. import sys
  3. from django.conf import settings
  4. from django.contrib import messages
  5. from django.db.models import ProtectedError, RestrictedError
  6. from django.http import JsonResponse
  7. from django.utils.html import escape
  8. from django.utils.safestring import mark_safe
  9. from django.utils.translation import gettext_lazy as _
  10. from rest_framework import status
  11. __all__ = (
  12. 'handle_protectederror',
  13. 'handle_rest_api_exception',
  14. )
  15. def handle_protectederror(obj_list, request, e):
  16. """
  17. Generate a user-friendly error message in response to a ProtectedError or RestrictedError exception.
  18. """
  19. if type(e) is ProtectedError:
  20. protected_objects = list(e.protected_objects)
  21. elif type(e) is RestrictedError:
  22. protected_objects = list(e.restricted_objects)
  23. else:
  24. raise e
  25. # Formulate the error message
  26. err_message = _("Unable to delete <strong>{objects}</strong>. {count} dependent objects were found: ").format(
  27. objects=', '.join(str(obj) for obj in obj_list),
  28. count=len(protected_objects) if len(protected_objects) <= 50 else _('More than 50')
  29. )
  30. # Append dependent objects to error message
  31. dependent_objects = []
  32. for dependent in protected_objects[:50]:
  33. if hasattr(dependent, 'get_absolute_url'):
  34. dependent_objects.append(f'<a href="{dependent.get_absolute_url()}">{escape(dependent)}</a>')
  35. else:
  36. dependent_objects.append(str(dependent))
  37. err_message += ', '.join(dependent_objects)
  38. messages.error(request, mark_safe(err_message))
  39. def handle_rest_api_exception(request, *args, **kwargs):
  40. """
  41. Handle exceptions and return a useful error message for REST API requests.
  42. """
  43. type_, error, traceback = sys.exc_info()
  44. data = {
  45. 'error': str(error),
  46. 'exception': type_.__name__,
  47. 'netbox_version': settings.VERSION,
  48. 'python_version': platform.python_version(),
  49. }
  50. return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)