mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Move serialize_object() & deserialize_object() to utilities.serialization
This commit is contained in:
parent
bbb8b7d010
commit
b92d3245c8
@ -1,9 +1,6 @@
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils import timezone
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.translation import gettext as _
|
||||
@ -15,9 +12,9 @@ from netbox.constants import RQ_QUEUE_DEFAULT
|
||||
from netbox.registry import registry
|
||||
from utilities.api import get_serializer_for_model
|
||||
from utilities.rqworker import get_rq_retry
|
||||
from utilities.utils import serialize_object
|
||||
from utilities.serialization import serialize_object
|
||||
from .choices import *
|
||||
from .models import EventRule, ScriptModule
|
||||
from .models import EventRule
|
||||
|
||||
logger = logging.getLogger('netbox.events_processor')
|
||||
|
||||
|
@ -8,7 +8,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from extras.choices import ChangeActionChoices
|
||||
from netbox.models import ChangeLoggedModel
|
||||
from netbox.models.features import *
|
||||
from utilities.utils import deserialize_object
|
||||
from utilities.serialization import deserialize_object
|
||||
|
||||
__all__ = (
|
||||
'Branch',
|
||||
|
@ -17,7 +17,7 @@ from netbox.config import get_config
|
||||
from netbox.registry import registry
|
||||
from netbox.signals import post_clean
|
||||
from utilities.json import CustomFieldJSONEncoder
|
||||
from utilities.utils import serialize_object
|
||||
from utilities.serialization import serialize_object
|
||||
from utilities.views import register_model_view
|
||||
|
||||
__all__ = (
|
||||
|
@ -6,7 +6,7 @@ from django.db.models.signals import m2m_changed, pre_delete, post_save
|
||||
|
||||
from extras.choices import ChangeActionChoices
|
||||
from extras.models import StagedChange
|
||||
from utilities.utils import serialize_object
|
||||
from utilities.serialization import serialize_object
|
||||
|
||||
logger = logging.getLogger('netbox.staging')
|
||||
|
||||
|
75
netbox/utilities/serialization.py
Normal file
75
netbox/utilities/serialization.py
Normal file
@ -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
|
@ -1,12 +1,9 @@
|
||||
import datetime
|
||||
import decimal
|
||||
import json
|
||||
from itertools import count, groupby
|
||||
from urllib.parse import urlencode
|
||||
|
||||
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.functions import Coalesce
|
||||
from django.http import QueryDict
|
||||
@ -14,9 +11,7 @@ from django.utils import timezone
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.utils.timezone import localtime
|
||||
from jinja2.sandbox import SandboxedEnvironment
|
||||
from mptt.models import MPTTModel
|
||||
|
||||
from extras.utils import is_taggable
|
||||
from netbox.config import get_config
|
||||
from .constants import HTML_ALLOWED_ATTRIBUTES, HTML_ALLOWED_TAGS
|
||||
from .string import title
|
||||
@ -96,69 +91,6 @@ def count_related(model, field):
|
||||
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=''):
|
||||
"""
|
||||
Translate a dictionary of attributes to a nested set of parameters suitable for QuerySet filtering. For example:
|
||||
|
Loading…
Reference in New Issue
Block a user