diff --git a/netbox/core/models/jobs.py b/netbox/core/models/jobs.py index fab4e00a0..73bcd13d6 100644 --- a/netbox/core/models/jobs.py +++ b/netbox/core/models/jobs.py @@ -39,7 +39,8 @@ class Job(models.Model): ) object = GenericForeignKey( ct_field='object_type', - fk_field='object_id' + fk_field='object_id', + for_concrete_model=False ) name = models.CharField( max_length=200 diff --git a/netbox/extras/views.py b/netbox/extras/views.py index cca9cab1c..bbc00d045 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -819,18 +819,9 @@ class ReportListView(ContentTypePermissionRequiredMixin, View): def get(self, request): report_modules = ReportModule.objects.restrict(request.user) - jobs = { - r.name: r - for r in Job.objects.filter( - object_type=ContentType.objects.get_by_natural_key('extras', 'reportmodule'), - status__in=JobStatusChoices.TERMINAL_STATE_CHOICES - ).order_by('name', '-created').distinct('name').defer('data') - } - return render(request, 'extras/report_list.html', { 'model': ReportModule, 'report_modules': report_modules, - 'jobs': jobs, }) @@ -986,18 +977,9 @@ class ScriptListView(ContentTypePermissionRequiredMixin, View): def get(self, request): script_modules = ScriptModule.objects.restrict(request.user) - jobs = { - r.name: r - for r in Job.objects.filter( - object_type=ContentType.objects.get_by_natural_key('extras', 'scriptmodule'), - status__in=JobStatusChoices.TERMINAL_STATE_CHOICES - ).order_by('name', '-created').distinct('name').defer('data') - } - return render(request, 'extras/script_list.html', { 'model': ScriptModule, 'script_modules': script_modules, - 'jobs': jobs, }) diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 5573b1abc..cf141d987 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -9,9 +9,9 @@ from django.db.models.signals import class_prepared from django.dispatch import receiver from django.utils import timezone from django.utils.translation import gettext as _ - from taggit.managers import TaggableManager +from core.choices import JobStatusChoices from extras.choices import CustomFieldVisibilityChoices, ObjectChangeActionChoices from extras.utils import is_taggable, register_features from netbox.registry import registry @@ -302,12 +302,24 @@ class JobsMixin(models.Model): jobs = GenericRelation( to='core.Job', content_type_field='object_type', - object_id_field='object_id' + object_id_field='object_id', + for_concrete_model=False ) class Meta: abstract = True + def get_latest_jobs(self): + """ + Return a dictionary mapping of the most recent jobs for this instance. + """ + return { + job.name: job + for job in self.jobs.filter( + status__in=JobStatusChoices.TERMINAL_STATE_CHOICES + ).order_by('name', '-created').distinct('name').defer('data') + } + class JournalingMixin(models.Model): """ diff --git a/netbox/templates/extras/report_list.html b/netbox/templates/extras/report_list.html index ea47b7886..e9eef966c 100644 --- a/netbox/templates/extras/report_list.html +++ b/netbox/templates/extras/report_list.html @@ -49,56 +49,58 @@ - {% for report_name, report in module.reports.items %} - {% with last_result=jobs|get_key:report.name %} - - - {{ report.name }} - - {{ report.description|markdown|placeholder }} - {% if last_result %} - - {{ last_result.created|annotated_date }} - - - {% badge last_result.get_status_display last_result.get_status_color %} - - {% else %} - Never - {{ ''|placeholder }} - {% endif %} - - {% if perms.extras.run_report %} -
-
- {% csrf_token %} - -
-
- {% endif %} - - - {% for method, stats in last_result.data.items %} + {% with jobs=module.get_latest_jobs %} + {% for report_name, report in module.reports.items %} + {% with last_job=jobs|get_key:report.name %} - - {{ method }} + + {{ report.name }} - - {{ stats.success }} - {{ stats.info }} - {{ stats.warning }} - {{ stats.failure }} + {{ report.description|markdown|placeholder }} + {% if last_job %} + + {{ last_job.created|annotated_date }} + + + {% badge last_job.get_status_display last_job.get_status_color %} + + {% else %} + Never + {{ ''|placeholder }} + {% endif %} + + {% if perms.extras.run_report %} +
+
+ {% csrf_token %} + +
+
+ {% endif %} - {% endfor %} - {% endwith %} - {% endfor %} + {% for method, stats in last_job.data.items %} + + + {{ method }} + + + {{ stats.success }} + {{ stats.info }} + {{ stats.warning }} + {{ stats.failure }} + + + {% endfor %} + {% endwith %} + {% endfor %} + {% endwith %} diff --git a/netbox/templates/extras/script_list.html b/netbox/templates/extras/script_list.html index 0f4907db6..ec8da9cf2 100644 --- a/netbox/templates/extras/script_list.html +++ b/netbox/templates/extras/script_list.html @@ -47,8 +47,8 @@ - {% for script_name, script_class in module.scripts.items %} - {% with last_result=jobs|get_key:script_class.name %} + {% with jobs=module.get_latest_jobs %} + {% for script_name, script_class in module.scripts.items %} {{ script_class.name }} @@ -56,20 +56,22 @@ {{ script_class.Meta.description|markdown|placeholder }} - {% if last_result %} - - {{ last_result.created|annotated_date }} - - - {% badge last_result.get_status_display last_result.get_status_color %} - - {% else %} - Never - {{ ''|placeholder }} - {% endif %} + {% with last_result=jobs|get_key:script_class.name %} + {% if last_result %} + + {{ last_result.created|annotated_date }} + + + {% badge last_result.get_status_display last_result.get_status_color %} + + {% else %} + Never + {{ ''|placeholder }} + {% endif %} + {% endwith %} - {% endwith %} - {% endfor %} + {% endfor %} + {% endwith %}