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

Move serialize_object() & deserialize_object() to utilities.serialization

Jeremy Stretch 1 год назад
Родитель
Сommit
b92d3245c8

+ 2 - 5
netbox/extras/events.py

@@ -1,9 +1,6 @@
-import logging
-
 from django.conf import settings
 from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
-from django.core.exceptions import ObjectDoesNotExist
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.module_loading import import_string
 from django.utils.module_loading import import_string
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
@@ -15,9 +12,9 @@ from netbox.constants import RQ_QUEUE_DEFAULT
 from netbox.registry import registry
 from netbox.registry import registry
 from utilities.api import get_serializer_for_model
 from utilities.api import get_serializer_for_model
 from utilities.rqworker import get_rq_retry
 from utilities.rqworker import get_rq_retry
-from utilities.utils import serialize_object
+from utilities.serialization import serialize_object
 from .choices import *
 from .choices import *
-from .models import EventRule, ScriptModule
+from .models import EventRule
 
 
 logger = logging.getLogger('netbox.events_processor')
 logger = logging.getLogger('netbox.events_processor')
 
 

+ 1 - 1
netbox/extras/models/staging.py

@@ -8,7 +8,7 @@ from django.utils.translation import gettext_lazy as _
 from extras.choices import ChangeActionChoices
 from extras.choices import ChangeActionChoices
 from netbox.models import ChangeLoggedModel
 from netbox.models import ChangeLoggedModel
 from netbox.models.features import *
 from netbox.models.features import *
-from utilities.utils import deserialize_object
+from utilities.serialization import deserialize_object
 
 
 __all__ = (
 __all__ = (
     'Branch',
     'Branch',

+ 1 - 1
netbox/netbox/models/features.py

@@ -17,7 +17,7 @@ from netbox.config import get_config
 from netbox.registry import registry
 from netbox.registry import registry
 from netbox.signals import post_clean
 from netbox.signals import post_clean
 from utilities.json import CustomFieldJSONEncoder
 from utilities.json import CustomFieldJSONEncoder
-from utilities.utils import serialize_object
+from utilities.serialization import serialize_object
 from utilities.views import register_model_view
 from utilities.views import register_model_view
 
 
 __all__ = (
 __all__ = (

+ 1 - 1
netbox/netbox/staging.py

@@ -6,7 +6,7 @@ from django.db.models.signals import m2m_changed, pre_delete, post_save
 
 
 from extras.choices import ChangeActionChoices
 from extras.choices import ChangeActionChoices
 from extras.models import StagedChange
 from extras.models import StagedChange
-from utilities.utils import serialize_object
+from utilities.serialization import serialize_object
 
 
 logger = logging.getLogger('netbox.staging')
 logger = logging.getLogger('netbox.staging')
 
 

+ 75 - 0
netbox/utilities/serialization.py

@@ -0,0 +1,75 @@
+import json
+
+from django.contrib.contenttypes.models import ContentType
+from django.core import serializers
+from mptt.models import MPTTModel
+
+from extras.utils import is_taggable
+
+__all__ = (
+    'deserialize_object',
+    'serialize_object',
+)
+
+
+def serialize_object(obj, resolve_tags=True, extra=None, exclude=None):
+    """
+    Return a generic JSON representation of an object using Django's built-in serializer. (This is used for things like
+    change logging, not the REST API.) Optionally include a dictionary to supplement the object data. A list of keys
+    can be provided to exclude them from the returned dictionary. Private fields (prefaced with an underscore) are
+    implicitly excluded.
+
+    Args:
+        obj: The object to serialize
+        resolve_tags: If true, any assigned tags will be represented by their names
+        extra: Any additional data to include in the serialized output. Keys provided in this mapping will
+            override object attributes.
+        exclude: An iterable of attributes to exclude from the serialized output
+    """
+    json_str = serializers.serialize('json', [obj])
+    data = json.loads(json_str)[0]['fields']
+    exclude = exclude or []
+
+    # Exclude any MPTTModel fields
+    if issubclass(obj.__class__, MPTTModel):
+        for field in ['level', 'lft', 'rght', 'tree_id']:
+            data.pop(field)
+
+    # Include custom_field_data as "custom_fields"
+    if hasattr(obj, 'custom_field_data'):
+        data['custom_fields'] = data.pop('custom_field_data')
+
+    # Resolve any assigned tags to their names. Check for tags cached on the instance;
+    # fall back to using the manager.
+    if resolve_tags and is_taggable(obj):
+        tags = getattr(obj, '_tags', None) or obj.tags.all()
+        data['tags'] = sorted([tag.name for tag in tags])
+
+    # Skip excluded and private (prefixes with an underscore) attributes
+    for key in list(data.keys()):
+        if key in exclude or (isinstance(key, str) and key.startswith('_')):
+            data.pop(key)
+
+    # Append any extra data
+    if extra is not None:
+        data.update(extra)
+
+    return data
+
+
+def deserialize_object(model, fields, pk=None):
+    """
+    Instantiate an object from the given model and field data. Functions as
+    the complement to serialize_object().
+    """
+    content_type = ContentType.objects.get_for_model(model)
+    if 'custom_fields' in fields:
+        fields['custom_field_data'] = fields.pop('custom_fields')
+    data = {
+        'model': '.'.join(content_type.natural_key()),
+        'pk': pk,
+        'fields': fields,
+    }
+    instance = list(serializers.deserialize('python', [data]))[0]
+
+    return instance

+ 0 - 68
netbox/utilities/utils.py

@@ -1,12 +1,9 @@
 import datetime
 import datetime
 import decimal
 import decimal
-import json
 from itertools import count, groupby
 from itertools import count, groupby
 from urllib.parse import urlencode
 from urllib.parse import urlencode
 
 
 import nh3
 import nh3
-from django.contrib.contenttypes.models import ContentType
-from django.core import serializers
 from django.db.models import Count, ManyToOneRel, OuterRef, Subquery
 from django.db.models import Count, ManyToOneRel, OuterRef, Subquery
 from django.db.models.functions import Coalesce
 from django.db.models.functions import Coalesce
 from django.http import QueryDict
 from django.http import QueryDict
@@ -14,9 +11,7 @@ from django.utils import timezone
 from django.utils.datastructures import MultiValueDict
 from django.utils.datastructures import MultiValueDict
 from django.utils.timezone import localtime
 from django.utils.timezone import localtime
 from jinja2.sandbox import SandboxedEnvironment
 from jinja2.sandbox import SandboxedEnvironment
-from mptt.models import MPTTModel
 
 
-from extras.utils import is_taggable
 from netbox.config import get_config
 from netbox.config import get_config
 from .constants import HTML_ALLOWED_ATTRIBUTES, HTML_ALLOWED_TAGS
 from .constants import HTML_ALLOWED_ATTRIBUTES, HTML_ALLOWED_TAGS
 from .string import title
 from .string import title
@@ -96,69 +91,6 @@ def count_related(model, field):
     return Coalesce(subquery, 0)
     return Coalesce(subquery, 0)
 
 
 
 
-def serialize_object(obj, resolve_tags=True, extra=None, exclude=None):
-    """
-    Return a generic JSON representation of an object using Django's built-in serializer. (This is used for things like
-    change logging, not the REST API.) Optionally include a dictionary to supplement the object data. A list of keys
-    can be provided to exclude them from the returned dictionary. Private fields (prefaced with an underscore) are
-    implicitly excluded.
-
-    Args:
-        obj: The object to serialize
-        resolve_tags: If true, any assigned tags will be represented by their names
-        extra: Any additional data to include in the serialized output. Keys provided in this mapping will
-            override object attributes.
-        exclude: An iterable of attributes to exclude from the serialized output
-    """
-    json_str = serializers.serialize('json', [obj])
-    data = json.loads(json_str)[0]['fields']
-    exclude = exclude or []
-
-    # Exclude any MPTTModel fields
-    if issubclass(obj.__class__, MPTTModel):
-        for field in ['level', 'lft', 'rght', 'tree_id']:
-            data.pop(field)
-
-    # Include custom_field_data as "custom_fields"
-    if hasattr(obj, 'custom_field_data'):
-        data['custom_fields'] = data.pop('custom_field_data')
-
-    # Resolve any assigned tags to their names. Check for tags cached on the instance;
-    # fall back to using the manager.
-    if resolve_tags and is_taggable(obj):
-        tags = getattr(obj, '_tags', None) or obj.tags.all()
-        data['tags'] = sorted([tag.name for tag in tags])
-
-    # Skip excluded and private (prefixes with an underscore) attributes
-    for key in list(data.keys()):
-        if key in exclude or (isinstance(key, str) and key.startswith('_')):
-            data.pop(key)
-
-    # Append any extra data
-    if extra is not None:
-        data.update(extra)
-
-    return data
-
-
-def deserialize_object(model, fields, pk=None):
-    """
-    Instantiate an object from the given model and field data. Functions as
-    the complement to serialize_object().
-    """
-    content_type = ContentType.objects.get_for_model(model)
-    if 'custom_fields' in fields:
-        fields['custom_field_data'] = fields.pop('custom_fields')
-    data = {
-        'model': '.'.join(content_type.natural_key()),
-        'pk': pk,
-        'fields': fields,
-    }
-    instance = list(serializers.deserialize('python', [data]))[0]
-
-    return instance
-
-
 def dict_to_filter_params(d, prefix=''):
 def dict_to_filter_params(d, prefix=''):
     """
     """
     Translate a dictionary of attributes to a nested set of parameters suitable for QuerySet filtering. For example:
     Translate a dictionary of attributes to a nested set of parameters suitable for QuerySet filtering. For example: