Introduce ObjectJobsView

This commit is contained in:
jeremystretch 2023-03-27 21:33:47 -04:00
parent 6861db2885
commit 431b21b5fe
6 changed files with 85 additions and 3 deletions

View File

@ -1,6 +1,5 @@
import logging import logging
from .choices import JobStatusChoices
from netbox.search.backends import search_backend from netbox.search.backends import search_backend
from .choices import * from .choices import *
from .exceptions import SyncError from .exceptions import SyncError
@ -13,7 +12,7 @@ def sync_datasource(job_result, *args, **kwargs):
""" """
Call sync() on a DataSource. Call sync() on a DataSource.
""" """
datasource = DataSource.objects.get(name=job_result.name) datasource = DataSource.objects.get(pk=job_result.object_id)
try: try:
job_result.start() job_result.start()

View File

@ -5,6 +5,7 @@ from fnmatch import fnmatchcase
from urllib.parse import urlparse from urllib.parse import urlparse
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import models from django.db import models
@ -70,6 +71,11 @@ class DataSource(JobsMixin, PrimaryModel):
null=True, null=True,
editable=False editable=False
) )
jobs = GenericRelation(
to='core.Job',
content_type_field='object_type',
object_id_field='object_id'
)
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)

View File

@ -162,7 +162,7 @@ class Job(models.Model):
self.trigger_webhooks(event=EVENT_JOB_END) self.trigger_webhooks(event=EVENT_JOB_END)
@classmethod @classmethod
def enqueue(cls, func, instance, name=None, user=None, schedule_at=None, interval=None, **kwargs): def enqueue(cls, func, instance, name='', user=None, schedule_at=None, interval=None, **kwargs):
""" """
Create a Job instance and enqueue a job using the given callable Create a Job instance and enqueue a job using the given callable

View File

@ -455,6 +455,12 @@ def _register_features(sender, **kwargs):
'changelog', 'changelog',
kwargs={'model': sender} kwargs={'model': sender}
)('netbox.views.generic.ObjectChangeLogView') )('netbox.views.generic.ObjectChangeLogView')
if issubclass(sender, JobsMixin):
register_model_view(
sender,
'jobs',
kwargs={'model': sender}
)('netbox.views.generic.ObjectJobsView')
if issubclass(sender, SyncedDataMixin): if issubclass(sender, SyncedDataMixin):
register_model_view( register_model_view(
sender, sender,

View File

@ -6,6 +6,8 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.views.generic import View from django.views.generic import View
from core.models import Job
from core.tables import JobTable
from extras import forms, tables from extras import forms, tables
from extras.models import * from extras.models import *
from utilities.permissions import get_permission_for_model from utilities.permissions import get_permission_for_model
@ -15,6 +17,7 @@ from .base import BaseMultiObjectView
__all__ = ( __all__ = (
'BulkSyncDataView', 'BulkSyncDataView',
'ObjectChangeLogView', 'ObjectChangeLogView',
'ObjectJobsView',
'ObjectJournalView', 'ObjectJournalView',
'ObjectSyncDataView', 'ObjectSyncDataView',
) )
@ -134,6 +137,59 @@ class ObjectJournalView(View):
}) })
class ObjectJobsView(View):
"""
Render a list of all Job assigned to an object. For example:
path('data-sources/<int:pk>/jobs/', ObjectJobsView.as_view(), name='datasource_jobs', kwargs={'model': DataSource}),
Attributes:
base_template: The name of the template to extend. If not provided, "{app}/{model}.html" will be used.
"""
base_template = None
tab = ViewTab(
label=_('Jobs'),
badge=lambda obj: obj.jobs.count(),
permission='core.view_job',
weight=11000
)
def get_object(self, request, **kwargs):
return get_object_or_404(self.model.objects.restrict(request.user, 'view'), **kwargs)
def get_jobs(self, instance):
object_type = ContentType.objects.get_for_model(instance)
return Job.objects.filter(
object_type=object_type,
object_id=instance.id
)
def get(self, request, model, **kwargs):
self.model = model
obj = self.get_object(request, **kwargs)
# Gather all Jobs for this object
jobs = self.get_jobs(obj)
jobs_table = JobTable(
data=jobs,
orderable=False,
user=request.user
)
jobs_table.configure(request)
# Default to using "<app>/<model>.html" as the template, if it exists. Otherwise,
# fall back to using base.html.
if self.base_template is None:
self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html"
return render(request, 'core/object_jobs.html', {
'object': obj,
'table': jobs_table,
'base_template': self.base_template,
'tab': self.tab,
})
class ObjectSyncDataView(View): class ObjectSyncDataView(View):
def post(self, request, model, **kwargs): def post(self, request, model, **kwargs):

View File

@ -0,0 +1,15 @@
{% extends base_template %}
{% load render_table from django_tables2 %}
{% block content %}
<div class="row mb-3">
<div class="col col-md-12">
<div class="card">
<div class="card-body table-responsive">
{% render_table table 'inc/table.html' %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
</div>
</div>
</div>
</div>
{% endblock %}