1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Adopt django-taggit-serializer for representation of assigned tags in the API

This commit is contained in:
Jeremy Stretch
2018-08-03 09:43:03 -04:00
committed by GitHub
parent ab37264ae1
commit f1bc88fc0c
11 changed files with 66 additions and 77 deletions

View File

@ -7,6 +7,7 @@ django-filter==1.1.0
django-mptt django-mptt
django-tables2 django-tables2
django-taggit django-taggit
django-taggit-serializer
django-timezone-field django-timezone-field
# https://github.com/encode/django-rest-framework/issues/6053 # https://github.com/encode/django-rest-framework/issues/6053
djangorestframework==3.8.1 djangorestframework==3.8.1

View File

@ -1,22 +1,22 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from rest_framework import serializers from rest_framework import serializers
from taggit.models import Tag from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from circuits.constants import CIRCUIT_STATUS_CHOICES from circuits.constants import CIRCUIT_STATUS_CHOICES
from circuits.models import Provider, Circuit, CircuitTermination, CircuitType from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
from dcim.api.serializers import NestedSiteSerializer, InterfaceSerializer from dcim.api.serializers import NestedSiteSerializer, InterfaceSerializer
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from tenancy.api.serializers import NestedTenantSerializer from tenancy.api.serializers import NestedTenantSerializer
from utilities.api import ChoiceField, TagField, ValidatedModelSerializer, WritableNestedSerializer from utilities.api import ChoiceField, ValidatedModelSerializer, WritableNestedSerializer
# #
# Providers # Providers
# #
class ProviderSerializer(CustomFieldModelSerializer): class ProviderSerializer(TaggitSerializer, CustomFieldModelSerializer):
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Provider model = Provider
@ -57,12 +57,12 @@ class NestedCircuitTypeSerializer(WritableNestedSerializer):
# Circuits # Circuits
# #
class CircuitSerializer(CustomFieldModelSerializer): class CircuitSerializer(TaggitSerializer, CustomFieldModelSerializer):
provider = NestedProviderSerializer() provider = NestedProviderSerializer()
status = ChoiceField(choices=CIRCUIT_STATUS_CHOICES, required=False) status = ChoiceField(choices=CIRCUIT_STATUS_CHOICES, required=False)
type = NestedCircuitTypeSerializer() type = NestedCircuitTypeSerializer()
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Circuit model = Circuit

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from rest_framework import serializers from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator from rest_framework.validators import UniqueTogetherValidator
from taggit.models import Tag from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from circuits.models import Circuit, CircuitTermination from circuits.models import Circuit, CircuitTermination
from dcim.constants import ( from dcim.constants import (
@ -20,7 +20,7 @@ from ipam.models import IPAddress, VLAN
from tenancy.api.serializers import NestedTenantSerializer from tenancy.api.serializers import NestedTenantSerializer
from users.api.serializers import NestedUserSerializer from users.api.serializers import NestedUserSerializer
from utilities.api import ( from utilities.api import (
ChoiceField, SerializedPKRelatedField, TagField, TimeZoneField, ValidatedModelSerializer, ChoiceField, SerializedPKRelatedField, TimeZoneField, ValidatedModelSerializer,
WritableNestedSerializer, WritableNestedSerializer,
) )
from virtualization.models import Cluster from virtualization.models import Cluster
@ -50,12 +50,12 @@ class RegionSerializer(serializers.ModelSerializer):
# Sites # Sites
# #
class SiteSerializer(CustomFieldModelSerializer): class SiteSerializer(TaggitSerializer, CustomFieldModelSerializer):
status = ChoiceField(choices=SITE_STATUS_CHOICES, required=False) status = ChoiceField(choices=SITE_STATUS_CHOICES, required=False)
region = NestedRegionSerializer(required=False, allow_null=True) region = NestedRegionSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
time_zone = TimeZoneField(required=False) time_zone = TimeZoneField(required=False)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Site model = Site
@ -118,14 +118,14 @@ class NestedRackRoleSerializer(WritableNestedSerializer):
# Racks # Racks
# #
class RackSerializer(CustomFieldModelSerializer): class RackSerializer(TaggitSerializer, CustomFieldModelSerializer):
site = NestedSiteSerializer() site = NestedSiteSerializer()
group = NestedRackGroupSerializer(required=False, allow_null=True) group = NestedRackGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
role = NestedRackRoleSerializer(required=False, allow_null=True) role = NestedRackRoleSerializer(required=False, allow_null=True)
type = ChoiceField(choices=RACK_TYPE_CHOICES, required=False) type = ChoiceField(choices=RACK_TYPE_CHOICES, required=False)
width = ChoiceField(choices=RACK_WIDTH_CHOICES, required=False) width = ChoiceField(choices=RACK_WIDTH_CHOICES, required=False)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Rack model = Rack
@ -220,12 +220,12 @@ class NestedManufacturerSerializer(WritableNestedSerializer):
# Device types # Device types
# #
class DeviceTypeSerializer(CustomFieldModelSerializer): class DeviceTypeSerializer(TaggitSerializer, CustomFieldModelSerializer):
manufacturer = NestedManufacturerSerializer() manufacturer = NestedManufacturerSerializer()
interface_ordering = ChoiceField(choices=IFACE_ORDERING_CHOICES, required=False) interface_ordering = ChoiceField(choices=IFACE_ORDERING_CHOICES, required=False)
subdevice_role = ChoiceField(choices=SUBDEVICE_ROLE_CHOICES, required=False) subdevice_role = ChoiceField(choices=SUBDEVICE_ROLE_CHOICES, required=False)
instance_count = serializers.IntegerField(source='instances.count', read_only=True) instance_count = serializers.IntegerField(source='instances.count', read_only=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = DeviceType model = DeviceType
@ -389,7 +389,7 @@ class DeviceVirtualChassisSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'master'] fields = ['id', 'url', 'master']
class DeviceSerializer(CustomFieldModelSerializer): class DeviceSerializer(TaggitSerializer, CustomFieldModelSerializer):
device_type = NestedDeviceTypeSerializer() device_type = NestedDeviceTypeSerializer()
device_role = NestedDeviceRoleSerializer() device_role = NestedDeviceRoleSerializer()
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
@ -404,7 +404,7 @@ class DeviceSerializer(CustomFieldModelSerializer):
parent_device = serializers.SerializerMethodField() parent_device = serializers.SerializerMethodField()
cluster = NestedClusterSerializer(required=False, allow_null=True) cluster = NestedClusterSerializer(required=False, allow_null=True)
virtual_chassis = DeviceVirtualChassisSerializer(required=False, allow_null=True) virtual_chassis = DeviceVirtualChassisSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Device model = Device
@ -459,9 +459,9 @@ class DeviceWithConfigContextSerializer(DeviceSerializer):
# Console server ports # Console server ports
# #
class ConsoleServerPortSerializer(ValidatedModelSerializer): class ConsoleServerPortSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = ConsoleServerPort model = ConsoleServerPort
@ -482,10 +482,10 @@ class NestedConsoleServerPortSerializer(WritableNestedSerializer):
# Console ports # Console ports
# #
class ConsolePortSerializer(ValidatedModelSerializer): class ConsolePortSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
cs_port = NestedConsoleServerPortSerializer(required=False, allow_null=True) cs_port = NestedConsoleServerPortSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = ConsolePort model = ConsolePort
@ -496,9 +496,9 @@ class ConsolePortSerializer(ValidatedModelSerializer):
# Power outlets # Power outlets
# #
class PowerOutletSerializer(ValidatedModelSerializer): class PowerOutletSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = PowerOutlet model = PowerOutlet
@ -519,10 +519,10 @@ class NestedPowerOutletSerializer(WritableNestedSerializer):
# Power ports # Power ports
# #
class PowerPortSerializer(ValidatedModelSerializer): class PowerPortSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
power_outlet = NestedPowerOutletSerializer(required=False, allow_null=True) power_outlet = NestedPowerOutletSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = PowerPort model = PowerPort
@ -569,7 +569,7 @@ class InterfaceVLANSerializer(WritableNestedSerializer):
fields = ['id', 'url', 'vid', 'name', 'display_name'] fields = ['id', 'url', 'vid', 'name', 'display_name']
class InterfaceSerializer(ValidatedModelSerializer): class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
form_factor = ChoiceField(choices=IFACE_FF_CHOICES, required=False) form_factor = ChoiceField(choices=IFACE_FF_CHOICES, required=False)
lag = NestedInterfaceSerializer(required=False, allow_null=True) lag = NestedInterfaceSerializer(required=False, allow_null=True)
@ -584,7 +584,7 @@ class InterfaceSerializer(ValidatedModelSerializer):
required=False, required=False,
many=True many=True
) )
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Interface model = Interface
@ -640,10 +640,10 @@ class InterfaceSerializer(ValidatedModelSerializer):
# Device bays # Device bays
# #
class DeviceBaySerializer(ValidatedModelSerializer): class DeviceBaySerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
installed_device = NestedDeviceSerializer(required=False, allow_null=True) installed_device = NestedDeviceSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = DeviceBay model = DeviceBay
@ -662,12 +662,12 @@ class NestedDeviceBaySerializer(WritableNestedSerializer):
# Inventory items # Inventory items
# #
class InventoryItemSerializer(ValidatedModelSerializer): class InventoryItemSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
# Provide a default value to satisfy UniqueTogetherValidator # Provide a default value to satisfy UniqueTogetherValidator
parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None) parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None)
manufacturer = NestedManufacturerSerializer() manufacturer = NestedManufacturerSerializer()
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = InventoryItem model = InventoryItem
@ -718,9 +718,9 @@ class ContextualInterfaceConnectionSerializer(serializers.ModelSerializer):
# Virtual chassis # Virtual chassis
# #
class VirtualChassisSerializer(ValidatedModelSerializer): class VirtualChassisSerializer(TaggitSerializer, ValidatedModelSerializer):
master = NestedDeviceSerializer() master = NestedDeviceSerializer()
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = VirtualChassis model = VirtualChassis

View File

@ -5,7 +5,7 @@ from collections import OrderedDict
from rest_framework import serializers from rest_framework import serializers
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from rest_framework.validators import UniqueTogetherValidator from rest_framework.validators import UniqueTogetherValidator
from taggit.models import Tag from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from dcim.api.serializers import NestedDeviceSerializer, InterfaceSerializer, NestedSiteSerializer from dcim.api.serializers import NestedDeviceSerializer, InterfaceSerializer, NestedSiteSerializer
from dcim.models import Interface from dcim.models import Interface
@ -16,7 +16,7 @@ from ipam.constants import (
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from tenancy.api.serializers import NestedTenantSerializer from tenancy.api.serializers import NestedTenantSerializer
from utilities.api import ( from utilities.api import (
ChoiceField, SerializedPKRelatedField, TagField, ValidatedModelSerializer, WritableNestedSerializer, ChoiceField, SerializedPKRelatedField, ValidatedModelSerializer, WritableNestedSerializer,
) )
from virtualization.api.serializers import NestedVirtualMachineSerializer from virtualization.api.serializers import NestedVirtualMachineSerializer
@ -25,9 +25,9 @@ from virtualization.api.serializers import NestedVirtualMachineSerializer
# VRFs # VRFs
# #
class VRFSerializer(CustomFieldModelSerializer): class VRFSerializer(TaggitSerializer, CustomFieldModelSerializer):
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = VRF model = VRF
@ -87,9 +87,9 @@ class NestedRIRSerializer(WritableNestedSerializer):
# Aggregates # Aggregates
# #
class AggregateSerializer(CustomFieldModelSerializer): class AggregateSerializer(TaggitSerializer, CustomFieldModelSerializer):
rir = NestedRIRSerializer() rir = NestedRIRSerializer()
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Aggregate model = Aggregate
@ -147,13 +147,13 @@ class NestedVLANGroupSerializer(WritableNestedSerializer):
# VLANs # VLANs
# #
class VLANSerializer(CustomFieldModelSerializer): class VLANSerializer(TaggitSerializer, CustomFieldModelSerializer):
site = NestedSiteSerializer(required=False, allow_null=True) site = NestedSiteSerializer(required=False, allow_null=True)
group = NestedVLANGroupSerializer(required=False, allow_null=True) group = NestedVLANGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceField(choices=VLAN_STATUS_CHOICES, required=False) status = ChoiceField(choices=VLAN_STATUS_CHOICES, required=False)
role = NestedRoleSerializer(required=False, allow_null=True) role = NestedRoleSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = VLAN model = VLAN
@ -190,14 +190,14 @@ class NestedVLANSerializer(WritableNestedSerializer):
# Prefixes # Prefixes
# #
class PrefixSerializer(CustomFieldModelSerializer): class PrefixSerializer(TaggitSerializer, CustomFieldModelSerializer):
site = NestedSiteSerializer(required=False, allow_null=True) site = NestedSiteSerializer(required=False, allow_null=True)
vrf = NestedVRFSerializer(required=False, allow_null=True) vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
vlan = NestedVLANSerializer(required=False, allow_null=True) vlan = NestedVLANSerializer(required=False, allow_null=True)
status = ChoiceField(choices=PREFIX_STATUS_CHOICES, required=False) status = ChoiceField(choices=PREFIX_STATUS_CHOICES, required=False)
role = NestedRoleSerializer(required=False, allow_null=True) role = NestedRoleSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Prefix model = Prefix
@ -254,13 +254,13 @@ class IPAddressInterfaceSerializer(serializers.ModelSerializer):
return reverse(url_name, kwargs={'pk': obj.pk}, request=self.context['request']) return reverse(url_name, kwargs={'pk': obj.pk}, request=self.context['request'])
class IPAddressSerializer(CustomFieldModelSerializer): class IPAddressSerializer(TaggitSerializer, CustomFieldModelSerializer):
vrf = NestedVRFSerializer(required=False, allow_null=True) vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
status = ChoiceField(choices=IPADDRESS_STATUS_CHOICES, required=False) status = ChoiceField(choices=IPADDRESS_STATUS_CHOICES, required=False)
role = ChoiceField(choices=IPADDRESS_ROLE_CHOICES, required=False) role = ChoiceField(choices=IPADDRESS_ROLE_CHOICES, required=False)
interface = IPAddressInterfaceSerializer(required=False, allow_null=True) interface = IPAddressInterfaceSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = IPAddress model = IPAddress

View File

@ -144,6 +144,7 @@ INSTALLED_APPS = [
'mptt', 'mptt',
'rest_framework', 'rest_framework',
'taggit', 'taggit',
'taggit_serializer',
'timezone_field', 'timezone_field',
'circuits', 'circuits',
'dcim', 'dcim',

View File

@ -2,12 +2,12 @@ from __future__ import unicode_literals
from rest_framework import serializers from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator from rest_framework.validators import UniqueTogetherValidator
from taggit.models import Tag from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from dcim.api.serializers import NestedDeviceSerializer from dcim.api.serializers import NestedDeviceSerializer
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from secrets.models import Secret, SecretRole from secrets.models import Secret, SecretRole
from utilities.api import TagField, ValidatedModelSerializer, WritableNestedSerializer from utilities.api import ValidatedModelSerializer, WritableNestedSerializer
# #
@ -33,11 +33,11 @@ class NestedSecretRoleSerializer(WritableNestedSerializer):
# Secrets # Secrets
# #
class SecretSerializer(CustomFieldModelSerializer): class SecretSerializer(TaggitSerializer, CustomFieldModelSerializer):
device = NestedDeviceSerializer() device = NestedDeviceSerializer()
role = NestedSecretRoleSerializer() role = NestedSecretRoleSerializer()
plaintext = serializers.CharField() plaintext = serializers.CharField()
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Secret model = Secret

View File

@ -1,11 +1,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from rest_framework import serializers from rest_framework import serializers
from taggit.models import Tag from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from utilities.api import TagField, ValidatedModelSerializer, WritableNestedSerializer from utilities.api import ValidatedModelSerializer, WritableNestedSerializer
# #
@ -31,9 +31,9 @@ class NestedTenantGroupSerializer(WritableNestedSerializer):
# Tenants # Tenants
# #
class TenantSerializer(CustomFieldModelSerializer): class TenantSerializer(TaggitSerializer, CustomFieldModelSerializer):
group = NestedTenantGroupSerializer(required=False) group = NestedTenantGroupSerializer(required=False)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Tenant model = Tenant

View File

@ -2,7 +2,6 @@ from __future__ import unicode_literals
from collections import OrderedDict from collections import OrderedDict
import pytz import pytz
from taggit.models import Tag
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -13,7 +12,7 @@ from rest_framework.exceptions import APIException
from rest_framework.permissions import BasePermission from rest_framework.permissions import BasePermission
from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import Field, ModelSerializer, RelatedField, ValidationError from rest_framework.serializers import Field, ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet as _ModelViewSet, ViewSet from rest_framework.viewsets import ModelViewSet as _ModelViewSet, ViewSet
from .utils import dynamic_import from .utils import dynamic_import
@ -56,20 +55,6 @@ class IsAuthenticatedOrLoginNotRequired(BasePermission):
# Fields # Fields
# #
class TagField(RelatedField):
"""
Represent a writable list of Tags associated with an object (use with many=True).
"""
def to_internal_value(self, data):
obj = self.parent.parent.instance
content_type = ContentType.objects.get_for_model(obj)
tag, _ = Tag.objects.get_or_create(content_type=content_type, object_id=obj.pk, name=data)
return tag
def to_representation(self, value):
return value.name
class ChoiceField(Field): class ChoiceField(Field):
""" """
Represent a ChoiceField as {'value': <DB value>, 'label': <string>}. Represent a ChoiceField as {'value': <DB value>, 'label': <string>}.
@ -147,9 +132,10 @@ class ValidatedModelSerializer(ModelSerializer):
""" """
def validate(self, data): def validate(self, data):
# Remove custom field data (if any) prior to model validation # Remove custom fields data and tags (if any) prior to model validation
attrs = data.copy() attrs = data.copy()
attrs.pop('custom_fields', None) attrs.pop('custom_fields', None)
attrs.pop('tags', None)
# Run clean() on an instance of the model # Run clean() on an instance of the model
if self.instance is None: if self.instance is None:

View File

@ -101,8 +101,8 @@ def serialize_object(obj, extra=None):
} }
# Include any tags # Include any tags
if hasattr(obj, 'tags'): # if hasattr(obj, 'tags'):
data['tags'] = [tag.name for tag in obj.tags.all()] # data['tags'] = [tag.name for tag in obj.tags.all()]
# Append any extra data # Append any extra data
if extra is not None: if extra is not None:

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from rest_framework import serializers from rest_framework import serializers
from taggit.models import Tag from taggit_serializer.serializers import TaggitSerializer, TagListSerializerField
from dcim.api.serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer from dcim.api.serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
from dcim.constants import IFACE_MODE_CHOICES from dcim.constants import IFACE_MODE_CHOICES
@ -9,7 +9,7 @@ from dcim.models import Interface
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from ipam.models import IPAddress, VLAN from ipam.models import IPAddress, VLAN
from tenancy.api.serializers import NestedTenantSerializer from tenancy.api.serializers import NestedTenantSerializer
from utilities.api import ChoiceField, TagField, ValidatedModelSerializer, WritableNestedSerializer from utilities.api import ChoiceField, ValidatedModelSerializer, WritableNestedSerializer
from virtualization.constants import VM_STATUS_CHOICES from virtualization.constants import VM_STATUS_CHOICES
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -56,11 +56,11 @@ class NestedClusterGroupSerializer(WritableNestedSerializer):
# Clusters # Clusters
# #
class ClusterSerializer(CustomFieldModelSerializer): class ClusterSerializer(TaggitSerializer, CustomFieldModelSerializer):
type = NestedClusterTypeSerializer() type = NestedClusterTypeSerializer()
group = NestedClusterGroupSerializer(required=False, allow_null=True) group = NestedClusterGroupSerializer(required=False, allow_null=True)
site = NestedSiteSerializer(required=False, allow_null=True) site = NestedSiteSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = Cluster model = Cluster
@ -90,7 +90,7 @@ class VirtualMachineIPAddressSerializer(serializers.ModelSerializer):
fields = ['id', 'url', 'family', 'address'] fields = ['id', 'url', 'family', 'address']
class VirtualMachineSerializer(CustomFieldModelSerializer): class VirtualMachineSerializer(TaggitSerializer, CustomFieldModelSerializer):
status = ChoiceField(choices=VM_STATUS_CHOICES, required=False) status = ChoiceField(choices=VM_STATUS_CHOICES, required=False)
cluster = NestedClusterSerializer(required=False, allow_null=True) cluster = NestedClusterSerializer(required=False, allow_null=True)
role = NestedDeviceRoleSerializer(required=False, allow_null=True) role = NestedDeviceRoleSerializer(required=False, allow_null=True)
@ -99,7 +99,7 @@ class VirtualMachineSerializer(CustomFieldModelSerializer):
primary_ip = VirtualMachineIPAddressSerializer(read_only=True) primary_ip = VirtualMachineIPAddressSerializer(read_only=True)
primary_ip4 = VirtualMachineIPAddressSerializer(required=False, allow_null=True) primary_ip4 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
primary_ip6 = VirtualMachineIPAddressSerializer(required=False, allow_null=True) primary_ip6 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
tags = TagField(queryset=Tag.objects.all(), required=False, many=True) tags = TagListSerializerField(required=False)
class Meta: class Meta:
model = VirtualMachine model = VirtualMachine

View File

@ -5,6 +5,7 @@ django-filter==1.1.0
django-mptt==0.9.1 django-mptt==0.9.1
django-tables2==1.21.2 django-tables2==1.21.2
django-taggit==0.22.2 django-taggit==0.22.2
django-taggit-serializer==0.1.7
django-timezone-field==2.1 django-timezone-field==2.1
djangorestframework==3.8.1 djangorestframework==3.8.1
drf-yasg[validation]==1.9.1 drf-yasg[validation]==1.9.1