diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 238037918..8493e7101 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -512,12 +512,10 @@ class ConfigTemplateSerializer(TaggableModelSerializer, ValidatedModelSerializer # class ScriptSerializer(ValidatedModelSerializer): - id = serializers.CharField(read_only=True) - url = serializers.HyperlinkedIdentityField(view_name='extras-api:script-detail',) + url = serializers.HyperlinkedIdentityField(view_name='extras-api:script-detail') description = serializers.SerializerMethodField(read_only=True) vars = serializers.SerializerMethodField(read_only=True) result = serializers.SerializerMethodField(read_only=True) - display = serializers.SerializerMethodField(read_only=True) class Meta: model = Script diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 99f0a840a..9106c1bcc 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -9,10 +9,9 @@ from rest_framework.generics import RetrieveUpdateDestroyAPIView from rest_framework.renderers import JSONRenderer from rest_framework.response import Response from rest_framework.routers import APIRootView -from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, ViewSet +from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from rq import Worker -from core.choices import JobStatusChoices from core.models import Job from extras import filtersets from extras.models import * @@ -216,7 +215,7 @@ class ConfigTemplateViewSet(SyncedDataMixin, ConfigTemplateRenderMixin, NetBoxMo class ScriptViewSet(ModelViewSet): permission_classes = [IsAuthenticatedOrLoginNotRequired] - queryset = Script.objects.all().prefetch_related('jobs') + queryset = Script.objects.prefetch_related('jobs') serializer_class = serializers.ScriptSerializer # filterset_class = filtersets.ScriptFilterSet @@ -225,20 +224,9 @@ class ScriptViewSet(ModelViewSet): lookup_value_regex = '[^/]+' # Allow dots def _get_script(self, pk): - # check if includes '.' for old module.script lookup - if '.' in pk: - try: - module_name, script_name = pk.split('.', maxsplit=1) - except ValueError: - raise Http404 - - module, script = get_module_and_script(module_name, script_name) - if script is None: - raise Http404 - else: - pk = int(pk) - script = get_object_or_404(self.queryset, pk=pk) - module = script.module + pk = int(pk) + script = get_object_or_404(self.queryset, pk=pk) + module = script.module return module, script diff --git a/netbox/extras/migrations/0108_script_models.py b/netbox/extras/migrations/0108_script_models.py index 7ff138912..badc4ca39 100644 --- a/netbox/extras/migrations/0108_script_models.py +++ b/netbox/extras/migrations/0108_script_models.py @@ -125,9 +125,9 @@ class Migration(migrations.Migration): name='Script', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=79)), - ('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scripts', to='extras.scriptmodule')), - ('is_executable', models.BooleanField(default=True)) + ('name', models.CharField(editable=False, max_length=79)), + ('module', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='scripts', to='extras.scriptmodule')), + ('is_executable', models.BooleanField(editable=False, default=True)) ], options={ 'ordering': ('module', 'name'), diff --git a/netbox/extras/models/scripts.py b/netbox/extras/models/scripts.py index 9bec04135..85aeb4f23 100644 --- a/netbox/extras/models/scripts.py +++ b/netbox/extras/models/scripts.py @@ -27,15 +27,18 @@ class Script(EventRulesMixin, JobsMixin, models.Model): name = models.CharField( verbose_name=_('name'), max_length=79, # Maximum length for a Python class name + editable=False, ) module = models.ForeignKey( to='extras.ScriptModule', on_delete=models.CASCADE, - related_name='scripts' + related_name='scripts', + editable=False ) is_executable = models.BooleanField( default=True, - verbose_name=_('is executable') + verbose_name=_('is executable'), + editable=False ) events = GenericRelation( 'extras.EventRule', @@ -51,7 +54,7 @@ class Script(EventRulesMixin, JobsMixin, models.Model): constraints = ( models.UniqueConstraint( fields=('name', 'module'), - name='%(app_label)s_%(class)s_unique_name_module' + name='extras_script_unique_name_module' ), ) verbose_name = _('script') @@ -65,7 +68,7 @@ class Script(EventRulesMixin, JobsMixin, models.Model): return self.module.get_module_scripts.get(self.name) def delete_if_no_jobs(self): - if self.jobs.all(): + if self.jobs.exists(): self.is_executable = False self.save() else: @@ -122,15 +125,11 @@ class ScriptModule(PythonModuleMixin, JobsMixin, ManagedFile): return scripts def sync_classes(self): - db_classes = {} - for obj in self.scripts.filter(module=self): - db_classes[obj.name] = obj - - db_classes_set = {k for k in db_classes.keys()} - - module_scripts = self.get_module_scripts - - module_classes_set = {k for k in module_scripts.keys()} + db_classes = { + script.name: script for script in self.scripts.all() + } + db_classes_set = set(db_classes.keys()) + module_classes_set = set(self.get_module_scripts.keys()) # remove any existing db classes if they are no longer in the file removed = db_classes_set - module_classes_set diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 7a177ef2e..fc49d1cad 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1069,11 +1069,6 @@ class BaseScriptView(ContentTypePermissionRequiredMixin, generic.ObjectView): self.script = get_object_or_404(Script.objects.all(), pk=pk) return self._init_vars(request) - def get_script_by_module_name(self, request, module, name): - module = get_script_module(module, request) - self.script = get_object_or_404(Script.objects.all(), module=module, name=name) - return self._init_vars(request) - class ScriptView(BaseScriptView):