Introduce get_latest_jobs() method on JobsMixin

This commit is contained in:
jeremystretch 2023-03-29 10:23:32 -04:00
parent c915d2360c
commit 556353c2f3
5 changed files with 81 additions and 82 deletions

View File

@ -39,7 +39,8 @@ class Job(models.Model):
) )
object = GenericForeignKey( object = GenericForeignKey(
ct_field='object_type', ct_field='object_type',
fk_field='object_id' fk_field='object_id',
for_concrete_model=False
) )
name = models.CharField( name = models.CharField(
max_length=200 max_length=200

View File

@ -819,18 +819,9 @@ class ReportListView(ContentTypePermissionRequiredMixin, View):
def get(self, request): def get(self, request):
report_modules = ReportModule.objects.restrict(request.user) 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', { return render(request, 'extras/report_list.html', {
'model': ReportModule, 'model': ReportModule,
'report_modules': report_modules, 'report_modules': report_modules,
'jobs': jobs,
}) })
@ -986,18 +977,9 @@ class ScriptListView(ContentTypePermissionRequiredMixin, View):
def get(self, request): def get(self, request):
script_modules = ScriptModule.objects.restrict(request.user) 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', { return render(request, 'extras/script_list.html', {
'model': ScriptModule, 'model': ScriptModule,
'script_modules': script_modules, 'script_modules': script_modules,
'jobs': jobs,
}) })

View File

@ -9,9 +9,9 @@ from django.db.models.signals import class_prepared
from django.dispatch import receiver from django.dispatch import receiver
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
from core.choices import JobStatusChoices
from extras.choices import CustomFieldVisibilityChoices, ObjectChangeActionChoices from extras.choices import CustomFieldVisibilityChoices, ObjectChangeActionChoices
from extras.utils import is_taggable, register_features from extras.utils import is_taggable, register_features
from netbox.registry import registry from netbox.registry import registry
@ -302,12 +302,24 @@ class JobsMixin(models.Model):
jobs = GenericRelation( jobs = GenericRelation(
to='core.Job', to='core.Job',
content_type_field='object_type', content_type_field='object_type',
object_id_field='object_id' object_id_field='object_id',
for_concrete_model=False
) )
class Meta: class Meta:
abstract = True 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): class JournalingMixin(models.Model):
""" """

View File

@ -49,56 +49,58 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for report_name, report in module.reports.items %} {% with jobs=module.get_latest_jobs %}
{% with last_result=jobs|get_key:report.name %} {% for report_name, report in module.reports.items %}
<tr> {% with last_job=jobs|get_key:report.name %}
<td>
<a href="{% url 'extras:report' module=module.path name=report.class_name %}" id="{{ report.module }}.{{ report.class_name }}">{{ report.name }}</a>
</td>
<td>{{ report.description|markdown|placeholder }}</td>
{% if last_result %}
<td>
<a href="{% url 'extras:report_result' job_pk=last_result.pk %}">{{ last_result.created|annotated_date }}</a>
</td>
<td>
{% badge last_result.get_status_display last_result.get_status_color %}
</td>
{% else %}
<td class="text-muted">Never</td>
<td>{{ ''|placeholder }}</td>
{% endif %}
<td>
{% if perms.extras.run_report %}
<div class="float-end noprint">
<form action="{% url 'extras:report' module=report.module name=report.class_name %}" method="post">
{% csrf_token %}
<button type="submit" name="_run" class="btn btn-primary btn-sm" style="width: 110px">
{% if last_result %}
<i class="mdi mdi-replay"></i> Run Again
{% else %}
<i class="mdi mdi-play"></i> Run Report
{% endif %}
</button>
</form>
</div>
{% endif %}
</td>
</tr>
{% for method, stats in last_result.data.items %}
<tr> <tr>
<td colspan="4" class="method"> <td>
<span class="ps-3">{{ method }}</span> <a href="{% url 'extras:report' module=module.path name=report.class_name %}" id="{{ report.module }}.{{ report.class_name }}">{{ report.name }}</a>
</td> </td>
<td class="text-end text-nowrap report-stats"> <td>{{ report.description|markdown|placeholder }}</td>
<span class="badge bg-success">{{ stats.success }}</span> {% if last_job %}
<span class="badge bg-info">{{ stats.info }}</span> <td>
<span class="badge bg-warning">{{ stats.warning }}</span> <a href="{% url 'extras:report_result' job_pk=last_job.pk %}">{{ last_job.created|annotated_date }}</a>
<span class="badge bg-danger">{{ stats.failure }}</span> </td>
<td>
{% badge last_job.get_status_display last_job.get_status_color %}
</td>
{% else %}
<td class="text-muted">Never</td>
<td>{{ ''|placeholder }}</td>
{% endif %}
<td>
{% if perms.extras.run_report %}
<div class="float-end noprint">
<form action="{% url 'extras:report' module=report.module name=report.class_name %}" method="post">
{% csrf_token %}
<button type="submit" name="_run" class="btn btn-primary btn-sm" style="width: 110px">
{% if last_job %}
<i class="mdi mdi-replay"></i> Run Again
{% else %}
<i class="mdi mdi-play"></i> Run Report
{% endif %}
</button>
</form>
</div>
{% endif %}
</td> </td>
</tr> </tr>
{% endfor %} {% for method, stats in last_job.data.items %}
{% endwith %} <tr>
{% endfor %} <td colspan="4" class="method">
<span class="ps-3">{{ method }}</span>
</td>
<td class="text-end text-nowrap report-stats">
<span class="badge bg-success">{{ stats.success }}</span>
<span class="badge bg-info">{{ stats.info }}</span>
<span class="badge bg-warning">{{ stats.warning }}</span>
<span class="badge bg-danger">{{ stats.failure }}</span>
</td>
</tr>
{% endfor %}
{% endwith %}
{% endfor %}
{% endwith %}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -47,8 +47,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for script_name, script_class in module.scripts.items %} {% with jobs=module.get_latest_jobs %}
{% with last_result=jobs|get_key:script_class.name %} {% for script_name, script_class in module.scripts.items %}
<tr> <tr>
<td> <td>
<a href="{% url 'extras:script' module=module.path name=script_name %}" name="script.{{ script_name }}">{{ script_class.name }}</a> <a href="{% url 'extras:script' module=module.path name=script_name %}" name="script.{{ script_name }}">{{ script_class.name }}</a>
@ -56,20 +56,22 @@
<td> <td>
{{ script_class.Meta.description|markdown|placeholder }} {{ script_class.Meta.description|markdown|placeholder }}
</td> </td>
{% if last_result %} {% with last_result=jobs|get_key:script_class.name %}
<td> {% if last_result %}
<a href="{% url 'extras:script_result' job_pk=last_result.pk %}">{{ last_result.created|annotated_date }}</a> <td>
</td> <a href="{% url 'extras:script_result' job_pk=last_result.pk %}">{{ last_result.created|annotated_date }}</a>
<td class="text-end"> </td>
{% badge last_result.get_status_display last_result.get_status_color %} <td class="text-end">
</td> {% badge last_result.get_status_display last_result.get_status_color %}
{% else %} </td>
<td class="text-muted">Never</td> {% else %}
<td class="text-end">{{ ''|placeholder }}</td> <td class="text-muted">Never</td>
{% endif %} <td class="text-end">{{ ''|placeholder }}</td>
{% endif %}
{% endwith %}
</tr> </tr>
{% endwith %} {% endfor %}
{% endfor %} {% endwith %}
</tbody> </tbody>
</table> </table>
</div> </div>