Enable modifying individual attributes via REST API

This commit is contained in:
Jeremy Stretch 2025-03-28 10:18:07 -04:00
parent 56d163eed1
commit 4fd3a91d2f
2 changed files with 24 additions and 2 deletions

View File

@ -5,7 +5,7 @@ from rest_framework import serializers
from dcim.choices import * from dcim.choices import *
from dcim.models import DeviceType, ModuleType, ModuleTypeProfile from dcim.models import DeviceType, ModuleType, ModuleTypeProfile
from netbox.api.fields import ChoiceField, RelatedObjectCountField from netbox.api.fields import AttributesField, ChoiceField, RelatedObjectCountField
from netbox.api.serializers import NetBoxModelSerializer from netbox.api.serializers import NetBoxModelSerializer
from netbox.choices import * from netbox.choices import *
from .manufacturers import ManufacturerSerializer from .manufacturers import ManufacturerSerializer
@ -95,12 +95,17 @@ class ModuleTypeSerializer(NetBoxModelSerializer):
required=False, required=False,
allow_null=True allow_null=True
) )
attributes = AttributesField(
source='attribute_data',
required=False,
allow_null=True
)
class Meta: class Meta:
model = ModuleType model = ModuleType
fields = [ fields = [
'id', 'url', 'display_url', 'display', 'profile', 'manufacturer', 'model', 'part_number', 'airflow', 'id', 'url', 'display_url', 'display', 'profile', 'manufacturer', 'model', 'part_number', 'airflow',
'weight', 'weight_unit', 'description', 'attribute_data', 'comments', 'tags', 'custom_fields', 'created', 'weight', 'weight_unit', 'description', 'attributes', 'comments', 'tags', 'custom_fields', 'created',
'last_updated', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'profile', 'manufacturer', 'model', 'description') brief_fields = ('id', 'url', 'display', 'profile', 'manufacturer', 'model', 'description')

View File

@ -9,6 +9,7 @@ from rest_framework.exceptions import ValidationError
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
__all__ = ( __all__ = (
'AttributesField',
'ChoiceField', 'ChoiceField',
'ContentTypeField', 'ContentTypeField',
'IPNetworkSerializer', 'IPNetworkSerializer',
@ -172,3 +173,19 @@ class IntegerRangeSerializer(serializers.Serializer):
def to_representation(self, instance): def to_representation(self, instance):
return instance.lower, instance.upper - 1 return instance.lower, instance.upper - 1
class AttributesField(serializers.JSONField):
"""
Custom attributes stored as JSON data.
"""
def to_internal_value(self, data):
data = super().to_internal_value(data)
# If updating an object, start with the initial attribute data. This enables the client to modify
# individual attributes without having to rewrite the entire field.
if data and self.parent.instance:
initial_data = getattr(self.parent.instance, self.source, None) or {}
return {**initial_data, **data}
return data