Просмотр исходного кода

Move ConfigContext classes out of models.py

Jeremy Stretch 4 лет назад
Родитель
Сommit
e97adcb614
3 измененных файлов с 165 добавлено и 156 удалено
  1. 2 4
      netbox/extras/models/__init__.py
  2. 161 0
      netbox/extras/models/configcontexts.py
  3. 2 152
      netbox/extras/models/models.py

+ 2 - 4
netbox/extras/models/__init__.py

@@ -1,9 +1,7 @@
 from .change_logging import ObjectChange
+from .configcontexts import ConfigContext, ConfigContextModel
 from .customfields import CustomField
-from .models import (
-    ConfigContext, ConfigContextModel, CustomLink, ExportTemplate, ImageAttachment, JobResult, Report, Script,
-    Webhook,
-)
+from .models import CustomLink, ExportTemplate, ImageAttachment, JobResult, Report, Script, Webhook
 from .tags import Tag, TaggedItem
 
 __all__ = (

+ 161 - 0
netbox/extras/models/configcontexts.py

@@ -0,0 +1,161 @@
+from collections import OrderedDict
+
+from django.core.validators import ValidationError
+from django.db import models
+from django.urls import reverse
+
+from extras.querysets import ConfigContextQuerySet
+from extras.utils import extras_features
+from netbox.models import ChangeLoggedModel
+from utilities.utils import deepmerge
+
+
+__all__ = (
+    'ConfigContext',
+    'ConfigContextModel',
+)
+
+
+#
+# Config contexts
+#
+
+@extras_features('webhooks')
+class ConfigContext(ChangeLoggedModel):
+    """
+    A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned
+    qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B
+    will be available to a Device in site A assigned to tenant B. Data is stored in JSON format.
+    """
+    name = models.CharField(
+        max_length=100,
+        unique=True
+    )
+    weight = models.PositiveSmallIntegerField(
+        default=1000
+    )
+    description = models.CharField(
+        max_length=200,
+        blank=True
+    )
+    is_active = models.BooleanField(
+        default=True,
+    )
+    regions = models.ManyToManyField(
+        to='dcim.Region',
+        related_name='+',
+        blank=True
+    )
+    site_groups = models.ManyToManyField(
+        to='dcim.SiteGroup',
+        related_name='+',
+        blank=True
+    )
+    sites = models.ManyToManyField(
+        to='dcim.Site',
+        related_name='+',
+        blank=True
+    )
+    roles = models.ManyToManyField(
+        to='dcim.DeviceRole',
+        related_name='+',
+        blank=True
+    )
+    platforms = models.ManyToManyField(
+        to='dcim.Platform',
+        related_name='+',
+        blank=True
+    )
+    cluster_groups = models.ManyToManyField(
+        to='virtualization.ClusterGroup',
+        related_name='+',
+        blank=True
+    )
+    clusters = models.ManyToManyField(
+        to='virtualization.Cluster',
+        related_name='+',
+        blank=True
+    )
+    tenant_groups = models.ManyToManyField(
+        to='tenancy.TenantGroup',
+        related_name='+',
+        blank=True
+    )
+    tenants = models.ManyToManyField(
+        to='tenancy.Tenant',
+        related_name='+',
+        blank=True
+    )
+    tags = models.ManyToManyField(
+        to='extras.Tag',
+        related_name='+',
+        blank=True
+    )
+    data = models.JSONField()
+
+    objects = ConfigContextQuerySet.as_manager()
+
+    class Meta:
+        ordering = ['weight', 'name']
+
+    def __str__(self):
+        return self.name
+
+    def get_absolute_url(self):
+        return reverse('extras:configcontext', kwargs={'pk': self.pk})
+
+    def clean(self):
+        super().clean()
+
+        # Verify that JSON data is provided as an object
+        if type(self.data) is not dict:
+            raise ValidationError(
+                {'data': 'JSON data must be in object form. Example: {"foo": 123}'}
+            )
+
+
+class ConfigContextModel(models.Model):
+    """
+    A model which includes local configuration context data. This local data will override any inherited data from
+    ConfigContexts.
+    """
+    local_context_data = models.JSONField(
+        blank=True,
+        null=True,
+    )
+
+    class Meta:
+        abstract = True
+
+    def get_config_context(self):
+        """
+        Return the rendered configuration context for a device or VM.
+        """
+
+        # Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs
+        data = OrderedDict()
+
+        if not hasattr(self, 'config_context_data'):
+            # The annotation is not available, so we fall back to manually querying for the config context objects
+            config_context_data = ConfigContext.objects.get_for_object(self, aggregate_data=True)
+        else:
+            # The attribute may exist, but the annotated value could be None if there is no config context data
+            config_context_data = self.config_context_data or []
+
+        for context in config_context_data:
+            data = deepmerge(data, context)
+
+        # If the object has local config context data defined, merge it last
+        if self.local_context_data:
+            data = deepmerge(data, self.local_context_data)
+
+        return data
+
+    def clean(self):
+        super().clean()
+
+        # Verify that JSON data is provided as an object
+        if self.local_context_data and type(self.local_context_data) is not dict:
+            raise ValidationError(
+                {'local_context_data': 'JSON data must be in object form. Example: {"foo": 123}'}
+            )

+ 2 - 152
netbox/extras/models/models.py

@@ -1,6 +1,5 @@
 import json
 import uuid
-from collections import OrderedDict
 
 from django.contrib.auth.models import User
 from django.contrib.contenttypes.fields import GenericForeignKey
@@ -8,22 +7,18 @@ from django.contrib.contenttypes.models import ContentType
 from django.core.validators import ValidationError
 from django.db import models
 from django.http import HttpResponse
-from django.urls import reverse
 from django.utils import timezone
 from rest_framework.utils.encoders import JSONEncoder
 
 from extras.choices import *
 from extras.constants import *
-from extras.querysets import ConfigContextQuerySet
 from extras.utils import extras_features, FeatureQuery, image_upload
-from netbox.models import BigIDModel, ChangeLoggedModel
+from netbox.models import BigIDModel
 from utilities.querysets import RestrictedQuerySet
-from utilities.utils import deepmerge, render_jinja2
+from utilities.utils import render_jinja2
 
 
 __all__ = (
-    'ConfigContext',
-    'ConfigContextModel',
     'CustomLink',
     'ExportTemplate',
     'ImageAttachment',
@@ -375,151 +370,6 @@ class ImageAttachment(BigIDModel):
             return None
 
 
-#
-# Config contexts
-#
-
-@extras_features('webhooks')
-class ConfigContext(ChangeLoggedModel):
-    """
-    A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned
-    qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B
-    will be available to a Device in site A assigned to tenant B. Data is stored in JSON format.
-    """
-    name = models.CharField(
-        max_length=100,
-        unique=True
-    )
-    weight = models.PositiveSmallIntegerField(
-        default=1000
-    )
-    description = models.CharField(
-        max_length=200,
-        blank=True
-    )
-    is_active = models.BooleanField(
-        default=True,
-    )
-    regions = models.ManyToManyField(
-        to='dcim.Region',
-        related_name='+',
-        blank=True
-    )
-    site_groups = models.ManyToManyField(
-        to='dcim.SiteGroup',
-        related_name='+',
-        blank=True
-    )
-    sites = models.ManyToManyField(
-        to='dcim.Site',
-        related_name='+',
-        blank=True
-    )
-    roles = models.ManyToManyField(
-        to='dcim.DeviceRole',
-        related_name='+',
-        blank=True
-    )
-    platforms = models.ManyToManyField(
-        to='dcim.Platform',
-        related_name='+',
-        blank=True
-    )
-    cluster_groups = models.ManyToManyField(
-        to='virtualization.ClusterGroup',
-        related_name='+',
-        blank=True
-    )
-    clusters = models.ManyToManyField(
-        to='virtualization.Cluster',
-        related_name='+',
-        blank=True
-    )
-    tenant_groups = models.ManyToManyField(
-        to='tenancy.TenantGroup',
-        related_name='+',
-        blank=True
-    )
-    tenants = models.ManyToManyField(
-        to='tenancy.Tenant',
-        related_name='+',
-        blank=True
-    )
-    tags = models.ManyToManyField(
-        to='extras.Tag',
-        related_name='+',
-        blank=True
-    )
-    data = models.JSONField()
-
-    objects = ConfigContextQuerySet.as_manager()
-
-    class Meta:
-        ordering = ['weight', 'name']
-
-    def __str__(self):
-        return self.name
-
-    def get_absolute_url(self):
-        return reverse('extras:configcontext', kwargs={'pk': self.pk})
-
-    def clean(self):
-        super().clean()
-
-        # Verify that JSON data is provided as an object
-        if type(self.data) is not dict:
-            raise ValidationError(
-                {'data': 'JSON data must be in object form. Example: {"foo": 123}'}
-            )
-
-
-class ConfigContextModel(models.Model):
-    """
-    A model which includes local configuration context data. This local data will override any inherited data from
-    ConfigContexts.
-    """
-    local_context_data = models.JSONField(
-        blank=True,
-        null=True,
-    )
-
-    class Meta:
-        abstract = True
-
-    def get_config_context(self):
-        """
-        Return the rendered configuration context for a device or VM.
-        """
-
-        # Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs
-        data = OrderedDict()
-
-        if not hasattr(self, 'config_context_data'):
-            # The annotation is not available, so we fall back to manually querying for the config context objects
-            config_context_data = ConfigContext.objects.get_for_object(self, aggregate_data=True)
-        else:
-            # The attribute may exist, but the annotated value could be None if there is no config context data
-            config_context_data = self.config_context_data or []
-
-        for context in config_context_data:
-            data = deepmerge(data, context)
-
-        # If the object has local config context data defined, merge it last
-        if self.local_context_data:
-            data = deepmerge(data, self.local_context_data)
-
-        return data
-
-    def clean(self):
-        super().clean()
-
-        # Verify that JSON data is provided as an object
-        if self.local_context_data and type(self.local_context_data) is not dict:
-            raise ValidationError(
-                {'local_context_data': 'JSON data must be in object form. Example: {"foo": 123}'}
-            )
-
-
 #
 # Custom scripts
 #