reports.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import inspect
  2. import logging
  3. from functools import cached_property
  4. from django.db import models
  5. from django.urls import reverse
  6. from django.utils.translation import gettext_lazy as _
  7. from core.choices import ManagedFileRootPathChoices
  8. from core.models import ManagedFile
  9. from extras.utils import is_report
  10. from netbox.models.features import JobsMixin, EventRulesMixin
  11. from utilities.querysets import RestrictedQuerySet
  12. from .mixins import PythonModuleMixin
  13. logger = logging.getLogger('netbox.reports')
  14. __all__ = (
  15. 'Report',
  16. 'ReportModule',
  17. )
  18. class Report(EventRulesMixin, models.Model):
  19. """
  20. Dummy model used to generate permissions for reports. Does not exist in the database.
  21. """
  22. class Meta:
  23. managed = False
  24. class ReportModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
  25. def get_queryset(self):
  26. return super().get_queryset().filter(file_root=ManagedFileRootPathChoices.REPORTS)
  27. class ReportModule(PythonModuleMixin, JobsMixin, ManagedFile):
  28. """
  29. Proxy model for report module files.
  30. """
  31. objects = ReportModuleManager()
  32. class Meta:
  33. proxy = True
  34. verbose_name = _('report module')
  35. verbose_name_plural = _('report modules')
  36. def get_absolute_url(self):
  37. return reverse('extras:report_list')
  38. def __str__(self):
  39. return self.python_name
  40. @cached_property
  41. def reports(self):
  42. def _get_name(cls):
  43. # For child objects in submodules use the full import path w/o the root module as the name
  44. return cls.full_name.split(".", maxsplit=1)[1]
  45. try:
  46. module = self.get_module()
  47. except (ImportError, SyntaxError) as e:
  48. logger.error(f"Unable to load report module {self.name}, exception: {e}")
  49. return {}
  50. reports = {}
  51. ordered = getattr(module, 'report_order', [])
  52. for cls in ordered:
  53. reports[_get_name(cls)] = cls
  54. for name, cls in inspect.getmembers(module, is_report):
  55. if cls not in ordered:
  56. reports[_get_name(cls)] = cls
  57. return reports
  58. def save(self, *args, **kwargs):
  59. self.file_root = ManagedFileRootPathChoices.REPORTS
  60. return super().save(*args, **kwargs)