Refactor extras.models

This commit is contained in:
jeremystretch 2023-03-24 21:25:22 -04:00
parent 5c0ce96b6f
commit ea1801bad3
8 changed files with 179 additions and 173 deletions

View File

@ -3,7 +3,7 @@ import pkgutil
from django.conf import settings
from django.db import migrations, models
import extras.models.models
import extras.models.mixins
def create_files(cls, root_name, root_path):
@ -60,7 +60,7 @@ class Migration(migrations.Migration):
'indexes': [],
'constraints': [],
},
bases=(extras.models.models.PythonModuleMixin, 'core.managedfile', models.Model),
bases=(extras.models.mixins.PythonModuleMixin, 'core.managedfile', models.Model),
),
migrations.CreateModel(
name='ScriptModule',
@ -71,7 +71,7 @@ class Migration(migrations.Migration):
'indexes': [],
'constraints': [],
},
bases=(extras.models.models.PythonModuleMixin, 'core.managedfile', models.Model),
bases=(extras.models.mixins.PythonModuleMixin, 'core.managedfile', models.Model),
),
# Instantiate ManagedFiles to represent scripts & reports

View File

@ -1,34 +1,10 @@
from .change_logging import ObjectChange
from .change_logging import *
from .configs import *
from .customfields import CustomField
from .dashboard import *
from .models import *
from .reports import *
from .scripts import *
from .search import *
from .staging import *
from .tags import Tag, TaggedItem
__all__ = (
'Branch',
'CachedValue',
'ConfigContext',
'ConfigContextModel',
'ConfigRevision',
'ConfigTemplate',
'CustomField',
'CustomLink',
'Dashboard',
'ExportTemplate',
'ImageAttachment',
'JobResult',
'JournalEntry',
'ObjectChange',
'Report',
'ReportModule',
'SavedFilter',
'Script',
'ScriptModule',
'StagedChange',
'Tag',
'TaggedItem',
'Webhook',
)
from .tags import *

View File

@ -7,6 +7,10 @@ from django.urls import reverse
from extras.choices import *
from utilities.querysets import RestrictedQuerySet
__all__ = (
'ObjectChange',
)
class ObjectChange(models.Model):
"""

View File

@ -0,0 +1,27 @@
import os
from pkgutil import ModuleInfo, get_importer
__all__ = (
'PythonModuleMixin',
)
class PythonModuleMixin:
@property
def path(self):
return os.path.splitext(self.file_path)[0]
def get_module_info(self):
path = os.path.dirname(self.full_path)
module_name = os.path.basename(self.path)
return ModuleInfo(
module_finder=get_importer(path),
name=module_name,
ispkg=False
)
def get_module(self):
importer, module_name, _ = self.get_module_info()
module = importer.find_module(module_name).load_module(module_name)
return module

View File

@ -1,9 +1,5 @@
import inspect
import json
import os
import uuid
from functools import cached_property
from pkgutil import ModuleInfo, get_importer
import django_rq
from django.conf import settings
@ -22,18 +18,15 @@ from django.utils.formats import date_format
from django.utils.translation import gettext as _
from rest_framework.utils.encoders import JSONEncoder
from core.choices import ManagedFileRootPathChoices
from core.models import ManagedFile
from extras.choices import *
from extras.conditions import ConditionSet
from extras.constants import *
from extras.utils import FeatureQuery, image_upload, is_report, is_script
from extras.utils import FeatureQuery, image_upload
from netbox.config import get_config
from netbox.constants import RQ_QUEUE_DEFAULT
from netbox.models import ChangeLoggedModel
from netbox.models.features import (
CloningMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, JobResultsMixin, SyncedDataMixin,
TagsMixin, WebhooksMixin,
CloningMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, SyncedDataMixin, TagsMixin,
)
from utilities.querysets import RestrictedQuerySet
from utilities.rqworker import get_queue_for_model
@ -46,11 +39,7 @@ __all__ = (
'ImageAttachment',
'JobResult',
'JournalEntry',
'Report',
'ReportModule',
'SavedFilter',
'Script',
'ScriptModule',
'Webhook',
)
@ -816,132 +805,3 @@ class ConfigRevision(models.Model):
@admin.display(boolean=True)
def is_active(self):
return cache.get('config_version') == self.pk
#
# Custom scripts & reports
#
class PythonModuleMixin:
@property
def path(self):
return os.path.splitext(self.file_path)[0]
def get_module_info(self):
path = os.path.dirname(self.full_path)
module_name = os.path.basename(self.path)
return ModuleInfo(
module_finder=get_importer(path),
name=module_name,
ispkg=False
)
def get_module(self):
importer, module_name, _ = self.get_module_info()
module = importer.find_module(module_name).load_module(module_name)
return module
class Script(JobResultsMixin, WebhooksMixin, models.Model):
"""
Dummy model used to generate permissions for custom scripts. Does not exist in the database.
"""
class Meta:
managed = False
class ScriptModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
def get_queryset(self):
return super().get_queryset().filter(file_root=ManagedFileRootPathChoices.SCRIPTS)
class ScriptModule(PythonModuleMixin, ManagedFile):
"""
Proxy model for script module files.
"""
objects = ScriptModuleManager()
class Meta:
proxy = True
def get_absolute_url(self):
return reverse('extras:script_list')
@cached_property
def scripts(self):
def _get_name(cls):
# For child objects in submodules use the full import path w/o the root module as the name
return cls.full_name.split(".", maxsplit=1)[1]
module = self.get_module()
scripts = {}
ordered = getattr(module, 'script_order', [])
for cls in ordered:
scripts[_get_name(cls)] = cls
for name, cls in inspect.getmembers(module, is_script):
if cls not in ordered:
scripts[_get_name(cls)] = cls
return scripts
def save(self, *args, **kwargs):
self.file_root = ManagedFileRootPathChoices.SCRIPTS
return super().save(*args, **kwargs)
#
# Reports
#
class Report(JobResultsMixin, WebhooksMixin, models.Model):
"""
Dummy model used to generate permissions for reports. Does not exist in the database.
"""
class Meta:
managed = False
class ReportModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
def get_queryset(self):
return super().get_queryset().filter(file_root=ManagedFileRootPathChoices.REPORTS)
class ReportModule(PythonModuleMixin, ManagedFile):
"""
Proxy model for report module files.
"""
objects = ReportModuleManager()
class Meta:
proxy = True
def get_absolute_url(self):
return reverse('extras:report_list')
@cached_property
def reports(self):
def _get_name(cls):
# For child objects in submodules use the full import path w/o the root module as the name
return cls.full_name.split(".", maxsplit=1)[1]
module = self.get_module()
reports = {}
ordered = getattr(module, 'report_order', [])
for cls in ordered:
reports[_get_name(cls)] = cls
for name, cls in inspect.getmembers(module, is_report):
if cls not in ordered:
reports[_get_name(cls)] = cls
return reports
def save(self, *args, **kwargs):
self.file_root = ManagedFileRootPathChoices.REPORTS
return super().save(*args, **kwargs)

View File

@ -0,0 +1,67 @@
import inspect
from functools import cached_property
from django.db import models
from django.urls import reverse
from core.choices import ManagedFileRootPathChoices
from core.models import ManagedFile
from extras.utils import is_report
from netbox.models.features import JobResultsMixin, WebhooksMixin
from utilities.querysets import RestrictedQuerySet
from .mixins import PythonModuleMixin
__all__ = (
'Report',
'ReportModule',
)
class Report(JobResultsMixin, WebhooksMixin, models.Model):
"""
Dummy model used to generate permissions for reports. Does not exist in the database.
"""
class Meta:
managed = False
class ReportModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
def get_queryset(self):
return super().get_queryset().filter(file_root=ManagedFileRootPathChoices.REPORTS)
class ReportModule(PythonModuleMixin, ManagedFile):
"""
Proxy model for report module files.
"""
objects = ReportModuleManager()
class Meta:
proxy = True
def get_absolute_url(self):
return reverse('extras:report_list')
@cached_property
def reports(self):
def _get_name(cls):
# For child objects in submodules use the full import path w/o the root module as the name
return cls.full_name.split(".", maxsplit=1)[1]
module = self.get_module()
reports = {}
ordered = getattr(module, 'report_order', [])
for cls in ordered:
reports[_get_name(cls)] = cls
for name, cls in inspect.getmembers(module, is_report):
if cls not in ordered:
reports[_get_name(cls)] = cls
return reports
def save(self, *args, **kwargs):
self.file_root = ManagedFileRootPathChoices.REPORTS
return super().save(*args, **kwargs)

View File

@ -0,0 +1,67 @@
import inspect
from functools import cached_property
from django.db import models
from django.urls import reverse
from core.choices import ManagedFileRootPathChoices
from core.models import ManagedFile
from extras.utils import is_script
from netbox.models.features import JobResultsMixin, WebhooksMixin
from utilities.querysets import RestrictedQuerySet
from .mixins import PythonModuleMixin
__all__ = (
'Script',
'ScriptModule',
)
class Script(JobResultsMixin, WebhooksMixin, models.Model):
"""
Dummy model used to generate permissions for custom scripts. Does not exist in the database.
"""
class Meta:
managed = False
class ScriptModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
def get_queryset(self):
return super().get_queryset().filter(file_root=ManagedFileRootPathChoices.SCRIPTS)
class ScriptModule(PythonModuleMixin, ManagedFile):
"""
Proxy model for script module files.
"""
objects = ScriptModuleManager()
class Meta:
proxy = True
def get_absolute_url(self):
return reverse('extras:script_list')
@cached_property
def scripts(self):
def _get_name(cls):
# For child objects in submodules use the full import path w/o the root module as the name
return cls.full_name.split(".", maxsplit=1)[1]
module = self.get_module()
scripts = {}
ordered = getattr(module, 'script_order', [])
for cls in ordered:
scripts[_get_name(cls)] = cls
for name, cls in inspect.getmembers(module, is_script):
if cls not in ordered:
scripts[_get_name(cls)] = cls
return scripts
def save(self, *args, **kwargs):
self.file_root = ManagedFileRootPathChoices.SCRIPTS
return super().save(*args, **kwargs)

View File

@ -9,6 +9,11 @@ from netbox.models.features import ExportTemplatesMixin
from utilities.choices import ColorChoices
from utilities.fields import ColorField
__all__ = (
'Tag',
'TaggedItem',
)
#
# Tags