Esempio n. 1
0
class RouterSerializer(TaggitSerializer, WriteEnabledNestedSerializer):
    configuration_template = TemplateNestedSerializer(required=False)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Router
        fields = [
            "id",
            "name",
            "hostname",
            "platform",
            "configuration_template",
            "comments",
            "netbox_device_id",
            "use_netbox",
            "tags",
        ]
        nested_fields = ["configuration_template"]
Esempio n. 2
0
class IPAddressSerializer(TaggitSerializer, CustomFieldModelSerializer):
    family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
    vrf = NestedVRFSerializer(required=False, allow_null=True)
    tenant = NestedTenantSerializer(required=False, allow_null=True)
    status = ChoiceField(choices=IPAddressStatusChoices, required=False)
    role = ChoiceField(choices=IPAddressRoleChoices, allow_blank=True, required=False)
    interface = IPAddressInterfaceSerializer(required=False, allow_null=True)
    nat_inside = NestedIPAddressSerializer(required=False, allow_null=True)
    nat_outside = NestedIPAddressSerializer(read_only=True)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = IPAddress
        fields = [
            'id', 'family', 'address', 'vrf', 'tenant', 'status', 'role', 'interface', 'nat_inside',
            'nat_outside', 'dns_name', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
        ]
        read_only_fields = ['family']
Esempio n. 3
0
class PersonSerializer(TaggitSerializer, serializers.ModelSerializer):
    tags = TagListSerializerField()
    user = UserSerializer()

    class Meta:
        model = Person
        fields = "__all__"

    def update(self, instance, validated_data):
        user_data = validated_data.pop('user')
        instance = super().update(instance, validated_data)
        instance.user.first_name = user_data.get('first_name',
                                                 instance.user.first_name)
        instance.user.last_name = user_data.get('last_name',
                                                instance.user.last_name)
        instance.user.email = user_data.get('email', instance.user.email)
        instance.user.save()
        return instance
Esempio n. 4
0
class AlbumListSerializer(serializers.ModelSerializer):
    tags = TagListSerializerField()
    cover_photo = PhotoListSerializer()

    class Meta:
        model = Album
        fields = (
            "id",
            "title",
            "description",
            "created_date",
            "published_date",
            "tags",
            "public",
            "created_by",
            "cover_photo",
        )
        read_only = True
Esempio n. 5
0
class ServiceSerializer(TaggitSerializer, CustomFieldModelSerializer):
    device = NestedDeviceSerializer(required=False, allow_null=True)
    virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True)
    protocol = ChoiceField(choices=ServiceProtocolChoices, required=False)
    ipaddresses = SerializedPKRelatedField(
        queryset=IPAddress.objects.all(),
        serializer=NestedIPAddressSerializer,
        required=False,
        many=True
    )
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Service
        fields = [
            'id', 'device', 'virtual_machine', 'name', 'port', 'protocol', 'ipaddresses', 'description', 'tags',
            'custom_fields', 'created', 'last_updated',
        ]
Esempio n. 6
0
class TenantSerializer(TaggitSerializer, CustomFieldModelSerializer):
    group = NestedTenantGroupSerializer(required=False)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Tenant
        fields = [
            'id',
            'name',
            'slug',
            'group',
            'description',
            'comments',
            'tags',
            'custom_fields',
            'created',
            'last_updated',
        ]
Esempio n. 7
0
class JobSerializer(TaggitSerializer, serializers.ModelSerializer):
    tags = TagListSerializerField()
    company = CompanySerializer()
    category = CategorySerializer()
    author = SimpleUserSerializer()

    class Meta:
        model = Job
        fields = [
            "id",
            "title",
            "description",
            "category",
            "company",
            "author",
            "state",
            "tags",
        ]
Esempio n. 8
0
class InterfaceSerializer(TaggitSerializer, ConnectedEndpointSerializer):
    device = NestedDeviceSerializer()
    type = ChoiceField(choices=IFACE_TYPE_CHOICES, required=False)
    # TODO: Remove in v2.7 (backward-compatibility for form_factor)
    form_factor = ChoiceField(choices=IFACE_TYPE_CHOICES, required=False)
    lag = NestedInterfaceSerializer(required=False, allow_null=True)
    mode = ChoiceField(choices=IFACE_MODE_CHOICES, required=False, allow_null=True)
    untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
    tagged_vlans = SerializedPKRelatedField(
        queryset=VLAN.objects.all(),
        serializer=NestedVLANSerializer,
        required=False,
        many=True
    )
    cable = NestedCableSerializer(read_only=True)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Interface
        fields = [
            'id', 'device', 'name', 'type', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only',
            'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', 'mode',
            'untagged_vlan', 'tagged_vlans', 'tags', 'count_ipaddresses',
        ]

    # TODO: This validation should be handled by Interface.clean()
    def validate(self, data):

        # All associated VLANs be global or assigned to the parent device's site.
        device = self.instance.device if self.instance else data.get('device')
        untagged_vlan = data.get('untagged_vlan')
        if untagged_vlan and untagged_vlan.site not in [device.site, None]:
            raise serializers.ValidationError({
                'untagged_vlan': "VLAN {} must belong to the same site as the interface's parent device, or it must be "
                                 "global.".format(untagged_vlan)
            })
        for vlan in data.get('tagged_vlans', []):
            if vlan.site not in [device.site, None]:
                raise serializers.ValidationError({
                    'tagged_vlans': "VLAN {} must belong to the same site as the interface's parent device, or it must "
                                    "be global.".format(vlan)
                })

        return super().validate(data)
Esempio n. 9
0
class TalkSerializer(TaggitSerializer, serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    code = serializers.CharField(required=True,
                                 allow_blank=False,
                                 max_length=100)
    title = serializers.CharField(required=True,
                                  allow_blank=False,
                                  max_length=200)
    slug = serializers.SlugField(read_only=True)
    description = serializers.CharField(
        required=False, style={'base_template': 'textarea.html'})
    duration = serializers.DurationField()
    youtube_url = serializers.URLField(read_only=True)
    default_thumb = serializers.URLField(read_only=True)
    medium_thumb = serializers.URLField(read_only=True)
    high_thumb = serializers.URLField(read_only=True)
    standard_thumb = serializers.URLField(read_only=True)
    maxres_thumb = serializers.URLField(read_only=True)
    view_count = serializers.IntegerField(default=0)
    like_count = serializers.IntegerField(default=0)
    dislike_count = serializers.IntegerField(default=0)
    favorite_count = serializers.IntegerField(default=0)
    youtube_view_count = serializers.IntegerField(default=0)
    youtube_like_count = serializers.IntegerField(default=0)
    youtube_dislike_count = serializers.IntegerField(default=0)
    youtube_favorite_count = serializers.IntegerField(default=0)
    total_view_count = serializers.IntegerField(default=0, read_only=True)
    total_like_count = serializers.IntegerField(default=0, read_only=True)
    total_dislike_count = serializers.IntegerField(default=0, read_only=True)
    total_favorite_count = serializers.IntegerField(default=0, read_only=True)
    wilsonscore_rank = serializers.FloatField(default=0)
    hacker_hot = serializers.FloatField(default=0)
    tags = TagListSerializerField()
    created = serializers.DateTimeField(default=timezone.now)
    updated = serializers.DateTimeField(default=timezone.now)

    class Meta:
        model = Talk
        fields = '__all__'
        read_only_fields = ('id', 'slug', 'youtube_url', 'default_thumb',
                            'medium_thumb', 'high_thumb', 'standard_thumb',
                            'maxres_thumb', 'total_view_count',
                            'total_like_count', 'total_dislike_count',
                            'total_favorite_count')
Esempio n. 10
0
class VLANSerializer(TaggitSerializer, CustomFieldModelSerializer):
    site = NestedSiteSerializer(required=False, allow_null=True)
    group = NestedVLANGroupSerializer(required=False, allow_null=True)
    tenant = NestedTenantSerializer(required=False, allow_null=True)
    status = ChoiceField(choices=VLANStatusChoices, required=False)
    role = NestedRoleSerializer(required=False, allow_null=True)
    tags = TagListSerializerField(required=False)
    prefix_count = serializers.IntegerField(read_only=True)

    class Meta:
        model = VLAN
        fields = [
            'id',
            'site',
            'group',
            'vid',
            'name',
            'tenant',
            'status',
            'role',
            'description',
            'tags',
            'display_name',
            'custom_fields',
            'created',
            'last_updated',
            'prefix_count',
        ]
        validators = []

    def validate(self, data):

        # Validate uniqueness of vid and name if a group has been assigned.
        if data.get('group', None):
            for field in ['vid', 'name']:
                validator = UniqueTogetherValidator(
                    queryset=VLAN.objects.all(), fields=('group', field))
                validator.set_context(self)
                validator(data)

        # Enforce model validation
        super().validate(data)

        return data
Esempio n. 11
0
class SiteSerializer(TaggitSerializer, CustomFieldModelSerializer):
    status = ChoiceField(choices=SITE_STATUS_CHOICES, required=False)
    region = NestedRegionSerializer(required=False, allow_null=True)
    tenant = NestedTenantSerializer(required=False, allow_null=True)
    time_zone = TimeZoneField(required=False)
    tags = TagListSerializerField(required=False)
    count_prefixes = serializers.IntegerField(read_only=True)
    count_vlans = serializers.IntegerField(read_only=True)
    count_racks = serializers.IntegerField(read_only=True)
    count_devices = serializers.IntegerField(read_only=True)
    count_circuits = serializers.IntegerField(read_only=True)

    class Meta:
        model = Site
        fields = [
            'id',
            'name',
            'slug',
            'status',
            'region',
            'tenant',
            'facility',
            'asn',
            'time_zone',
            'description',
            'physical_address',
            'shipping_address',
            'latitude',
            'longitude',
            'contact_name',
            'contact_phone',
            'contact_email',
            'comments',
            'tags',
            'custom_fields',
            'created',
            'last_updated',
            'count_prefixes',
            'count_vlans',
            'count_racks',
            'count_devices',
            'count_circuits',
        ]
Esempio n. 12
0
class ImageSerializer(TaggitSerializer, serializers.ModelSerializer):

    comments = CommentSerializer(many=True)
    creator = FeedUserSerializer()
    tags = TagListSerializerField()

    class Meta:
        model = models.Image
        fields = (
            'id',
            'file',
            'location',
            'caption',
            'comments',
            'like_count',
            'creator',
            'tags',
            'natural_time',
        )
Esempio n. 13
0
class InterfaceSerializer(TaggitSerializer, IsConnectedMixin, ValidatedModelSerializer):
    device = NestedDeviceSerializer()
    form_factor = ChoiceField(choices=IFACE_FF_CHOICES, required=False)
    lag = NestedInterfaceSerializer(required=False, allow_null=True)
    connected_endpoint = NestedInterfaceSerializer(required=False, allow_null=True)
    is_connected = serializers.SerializerMethodField(read_only=True)
    circuit_termination = InterfaceCircuitTerminationSerializer(read_only=True)
    mode = ChoiceField(choices=IFACE_MODE_CHOICES, required=False, allow_null=True)
    untagged_vlan = InterfaceVLANSerializer(required=False, allow_null=True)
    tagged_vlans = SerializedPKRelatedField(
        queryset=VLAN.objects.all(),
        serializer=InterfaceVLANSerializer,
        required=False,
        many=True
    )
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Interface
        fields = [
            'id', 'device', 'name', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', 'description',
            'is_connected', 'connected_endpoint', 'circuit_termination', 'mode', 'untagged_vlan', 'tagged_vlans',
            'tags',
        ]

    def validate(self, data):

        # All associated VLANs be global or assigned to the parent device's site.
        device = self.instance.device if self.instance else data.get('device')
        untagged_vlan = data.get('untagged_vlan')
        if untagged_vlan and untagged_vlan.site not in [device.site, None]:
            raise serializers.ValidationError({
                'untagged_vlan': "VLAN {} must belong to the same site as the interface's parent device, or it must be "
                                 "global.".format(untagged_vlan)
            })
        for vlan in data.get('tagged_vlans', []):
            if vlan.site not in [device.site, None]:
                raise serializers.ValidationError({
                    'tagged_vlans': "VLAN {} must belong to the same site as the interface's parent device, or it must "
                                    "be global.".format(vlan)
                })

        return super(InterfaceSerializer, self).validate(data)
Esempio n. 14
0
class SecretSerializer(TaggitSerializer, CustomFieldModelSerializer):
    device = NestedDeviceSerializer()
    role = NestedSecretRoleSerializer()
    plaintext = serializers.CharField()
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Secret
        fields = [
            'id',
            'device',
            'role',
            'name',
            'plaintext',
            'hash',
            'tags',
            'custom_fields',
            'created',
            'last_updated',
        ]
        validators = []

    def validate(self, data):

        # Encrypt plaintext data using the master key provided from the view context
        if data.get('plaintext'):
            s = Secret(plaintext=data['plaintext'])
            s.encrypt(self.context['master_key'])
            data['ciphertext'] = s.ciphertext
            data['hash'] = s.hash

        # Validate uniqueness of name if one has been provided.
        if data.get('name'):
            validator = UniqueTogetherValidator(queryset=Secret.objects.all(),
                                                fields=('device', 'role',
                                                        'name'))
            validator.set_context(self)
            validator(data)

        # Enforce model validation
        super(SecretSerializer, self).validate(data)

        return data
Esempio n. 15
0
class ImageSerializer(TaggitSerializer, ModelSerializer):
    permissions = DRYPermissionsField()
    image = ImageField()
    image_thumb = ImageField(read_only=True)
    image_small = ImageField(read_only=True)
    image_medium = ImageField(read_only=True)
    image_large = ImageField(read_only=True)
    owner_name = SerializerMethodField()
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Image
        fields = ('id', 'title', 'description', 'owner', 'image_thumb',
                  'image_small', 'image', 'image_medium', 'image_large',
                  'created', 'updated', 'permissions', 'owner_name', 'tags',
                  'source')

    def get_owner_name(self, obj):
        return obj.owner.username
Esempio n. 16
0
class ResoucesSerializer(serializers.ModelSerializer):

    tags = TagListSerializerField()
    comments = CommentSerialzier(many=True, read_only=True)

    class Meta:
        model = Resources
        fields = (
            'id',
            'title',
            'author',
            'description',
            'tags',
            'resource_type',
            'thumbnail',
            'slug',
            'url',
            'comments',
        )
Esempio n. 17
0
class VirtualMachineSerializer(TaggitSerializer, CustomFieldModelSerializer):
    status = ChoiceField(choices=VM_STATUS_CHOICES, required=False)
    site = NestedSiteSerializer(read_only=True)
    cluster = NestedClusterSerializer(required=False, allow_null=True)
    role = NestedDeviceRoleSerializer(required=False, allow_null=True)
    tenant = NestedTenantSerializer(required=False, allow_null=True)
    platform = NestedPlatformSerializer(required=False, allow_null=True)
    primary_ip = VirtualMachineIPAddressSerializer(read_only=True)
    primary_ip4 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
    primary_ip6 = VirtualMachineIPAddressSerializer(required=False, allow_null=True)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = VirtualMachine
        fields = [
            'id', 'name', 'status', 'site', 'cluster', 'role', 'tenant', 'platform', 'primary_ip', 'primary_ip4',
            'primary_ip6', 'vcpus', 'memory', 'disk', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
            'local_context_data',
        ]
Esempio n. 18
0
class PostSerializer(TaggitSerializer,serializers.ModelSerializer):
    tags = TagListSerializerField()
    class Meta:
        model = Post
        fields = [
            'autherName',
            'title',
            'slug',
            'author',
            'body',
            'publish',
            'created',
            'updated',
            'status',
            'publishDate',
            'tags',
            'id',
        ]
        extra_kwargs = {'publish': {'read_only': True,'format':'%Y/%m/%d  %H:%M'} , 'tags':{"unique":True}}
Esempio n. 19
0
class TravelSerializer(TaggitSerializer, serializers.ModelSerializer):

    """
    Feed 페이지에 사용되는 시리얼라이져
    """

    owner = FeedUserserializer(read_only=True) # 사용자
    status = serializers.CharField(
        read_only=True, 
        source='get_status_display'
    ) # Model.get_FOO_display를 통해 human-readable 값을 불러올수 있음
    travel_plan = TravelPlanSerializer(many=True) # 여행계획
    tags = TagListSerializerField() # 태그
    main_image = serializers.FileField(read_only=True)

    class Meta:
        model = Travel
        fields = (
            'id',
            'main_image',
            'title',
            'status',
            'owner',
            'price',
            'travel_plan',
            'travel_region',
            'tags',
            'start_at',
            'end_at',
        )

    def create(self, validate_data):
        travel_plan = validate_data.pop('travel_plan') # 여행 계획 리스트
        tags = validate_data.pop('tags') # 태그 리스트 
        travel = Travel.objects.create(**validate_data) # 여행 instance 생성
        travel.tags.set(*tags) # 태그 저장

        for plan in travel_plan:
            plan = TravelPlan.objects.create(**plan)
            plan.travel = travel
            travel.travel_plan.add(plan)
            print(travel)
        return travel
Esempio n. 20
0
class MediaItemSerializer(TaggitSerializer, ModelSerializer):
    """

    Store and retrieve media items

    """
    tags = TagListSerializerField()
    uploader = PrimaryKeyRelatedField(
        # set it to read_only as we're handling the writing part ourselves
        read_only=True,
        default=CurrentUserDefault())

    class Meta:
        model = MediaItem
        fields = [
            'id', 'format', 'name', 'creator', 'uploader', 'language',
            'uploaded', 'rights', 'duration', 'tags', 'mediaFile', 'mediaUrl'
        ]
        ordering = ['-id']
Esempio n. 21
0
class ImageSerializer(TaggitSerializer, serializers.ModelSerializer
                      ):  # 이미지  아이디, 이미지파일, 위치, 캡션, 게시글, 좋아요횟수
    # comment, like 직렬화
    comments = CommentSerializer(many=True)
    creator = FeedUserSerializer()
    tags = TagListSerializerField()

    class Meta:
        model = models.Image
        fields = (
            'id',
            'creator',
            'file',
            'location',
            'caption',
            'comments',
            'tags',
            'like_count',
        )
Esempio n. 22
0
class AdventureDesignSerializer(serializers.HyperlinkedModelSerializer,
                                TaggitSerializer):
    """Serializer used for the designer app. Includes additional info."""
    authors = serializers.StringRelatedField(many=True)
    tags = TagListSerializerField()

    # rooms_count = serializers.IntegerField()
    # artifacts_count = serializers.IntegerField()
    # effects_count = serializers.IntegerField()
    # monsters_count = serializers.IntegerField()

    class Meta:
        model = Adventure
        fields = (
            'id', 'name', 'description', 'full_description', 'intro_text',
            'intro_question', 'slug', 'featured_month', 'date_published',
            'authors', 'tags', 'times_played', 'active'
            # 'rooms_count', 'artifacts_count', 'effects_count', 'monsters_count'
        )
Esempio n. 23
0
class AggregateSerializer(TaggitSerializer, CustomFieldModelSerializer):
    rir = NestedRIRSerializer()
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Aggregate
        fields = [
            'id',
            'family',
            'prefix',
            'rir',
            'date_added',
            'description',
            'tags',
            'custom_fields',
            'created',
            'last_updated',
        ]
        read_only_fields = ['family']
Esempio n. 24
0
class ImageSerializer(TaggitSerializer, serializers.ModelSerializer):

    comments = CommentSerializer(many=True)
    creator = FeedUserSerializer()
    tags = TagListSerializerField()

    class Meta:
        model = models.Image
        fields = (
            "id",
            "file",
            "location",
            "caption",
            "comments",
            "like_count",
            "creator",
            'tags',
            'created_at',
        )
Esempio n. 25
0
class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
    virtual_machine = NestedVirtualMachineSerializer()
    type = ChoiceField(choices=VMInterfaceTypeChoices, default=VMInterfaceTypeChoices.TYPE_VIRTUAL, required=False)
    mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False)
    untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
    tagged_vlans = SerializedPKRelatedField(
        queryset=VLAN.objects.all(),
        serializer=NestedVLANSerializer,
        required=False,
        many=True
    )
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Interface
        fields = [
            'id', 'virtual_machine', 'name', 'type', 'enabled', 'mtu', 'mac_address', 'description', 'mode',
            'untagged_vlan', 'tagged_vlans', 'tags',
        ]
Esempio n. 26
0
class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
    virtual_machine = NestedVirtualMachineSerializer()
    form_factor = ChoiceField(choices=IFACE_FF_CHOICES, default=IFACE_FF_VIRTUAL, required=False)
    mode = ChoiceField(choices=IFACE_MODE_CHOICES, required=False, allow_null=True)
    untagged_vlan = InterfaceVLANSerializer(required=False, allow_null=True)
    tagged_vlans = SerializedPKRelatedField(
        queryset=VLAN.objects.all(),
        serializer=InterfaceVLANSerializer,
        required=False,
        many=True
    )
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Interface
        fields = [
            'id', 'virtual_machine', 'name', 'form_factor', 'enabled', 'mtu', 'mac_address', 'description', 'mode',
            'untagged_vlan', 'tagged_vlans', 'tags',
        ]
Esempio n. 27
0
class ConsoleServerPortSerializer(TaggitSerializer,
                                  ConnectedEndpointSerializer):
    device = NestedDeviceSerializer()
    cable = NestedCableSerializer(read_only=True)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = ConsoleServerPort
        fields = [
            'id',
            'device',
            'name',
            'description',
            'connected_endpoint_type',
            'connected_endpoint',
            'connection_status',
            'cable',
            'tags',
        ]
Esempio n. 28
0
class VRFSerializer(TaggitSerializer, CustomFieldModelSerializer):
    tenant = NestedTenantSerializer(required=False, allow_null=True)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = VRF
        fields = [
            'id',
            'name',
            'rd',
            'tenant',
            'enforce_unique',
            'description',
            'tags',
            'display_name',
            'custom_fields',
            'created',
            'last_updated',
        ]
Esempio n. 29
0
class QASerializer(TaggitSerializer, serializers.ModelSerializer):
    user = serializers.StringRelatedField(read_only=True)

    #comments = serializers.StringRelatedField(many=True)
    answers = AnswerSerializer(many=True, read_only=True)
    #tags = TagsField(source="get_tags")
    tags = TagListSerializerField()

    #def create(self, validated_data):
    # using "source=get_tags" drf "thinks" get_tags is a real field name, so the
    # return value of to_internal_value() is used a the value of a key called "get_tags" inside validated_data dict. We need to remove it and handle the tags manually.
    #tags = validated_data.pop("get_tags")
    #qa = QA.objects.create(**validated_data)
    #qa.tags.add(*tags)

    #return qa

    class Meta:
        model = QA
        fields = '__all__'
Esempio n. 30
0
class ClusterSerializer(TaggitSerializer, CustomFieldModelSerializer):
    type = NestedClusterTypeSerializer()
    group = NestedClusterGroupSerializer(required=False, allow_null=True)
    site = NestedSiteSerializer(required=False, allow_null=True)
    tags = TagListSerializerField(required=False)

    class Meta:
        model = Cluster
        fields = [
            'id',
            'name',
            'type',
            'group',
            'site',
            'comments',
            'tags',
            'custom_fields',
            'created',
            'last_updated',
        ]