mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Add tags to organizational & nested group models
This commit is contained in:
@@ -6,7 +6,7 @@ from dcim.choices import InterfaceModeChoices
|
||||
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
|
||||
from ipam.models import VLAN
|
||||
from netbox.api import ChoiceField, SerializedPKRelatedField
|
||||
from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from tenancy.api.nested_serializers import NestedTenantSerializer
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||
@@ -17,26 +17,26 @@ from .nested_serializers import *
|
||||
# Clusters
|
||||
#
|
||||
|
||||
class ClusterTypeSerializer(OrganizationalModelSerializer):
|
||||
class ClusterTypeSerializer(PrimaryModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustertype-detail')
|
||||
cluster_count = serializers.IntegerField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'custom_fields', 'created', 'last_updated',
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'cluster_count',
|
||||
]
|
||||
|
||||
|
||||
class ClusterGroupSerializer(OrganizationalModelSerializer):
|
||||
class ClusterGroupSerializer(PrimaryModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustergroup-detail')
|
||||
cluster_count = serializers.IntegerField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'custom_fields', 'created', 'last_updated',
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'cluster_count',
|
||||
]
|
||||
|
||||
|
@@ -23,7 +23,7 @@ class VirtualizationRootView(APIRootView):
|
||||
class ClusterTypeViewSet(CustomFieldModelViewSet):
|
||||
queryset = ClusterType.objects.annotate(
|
||||
cluster_count=count_related(Cluster, 'type')
|
||||
)
|
||||
).prefetch_related('tags')
|
||||
serializer_class = serializers.ClusterTypeSerializer
|
||||
filterset_class = filtersets.ClusterTypeFilterSet
|
||||
|
||||
@@ -31,7 +31,7 @@ class ClusterTypeViewSet(CustomFieldModelViewSet):
|
||||
class ClusterGroupViewSet(CustomFieldModelViewSet):
|
||||
queryset = ClusterGroup.objects.annotate(
|
||||
cluster_count=count_related(Cluster, 'group')
|
||||
)
|
||||
).prefetch_related('tags')
|
||||
serializer_class = serializers.ClusterGroupSerializer
|
||||
filterset_class = filtersets.ClusterGroupFilterSet
|
||||
|
||||
|
@@ -23,7 +23,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ClusterTypeBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
class ClusterTypeBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ClusterType.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -37,7 +37,7 @@ class ClusterTypeBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
nullable_fields = ['description']
|
||||
|
||||
|
||||
class ClusterGroupBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
class ClusterGroupBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
|
@@ -28,22 +28,30 @@ __all__ = (
|
||||
|
||||
class ClusterTypeForm(BootstrapMixin, CustomFieldModelForm):
|
||||
slug = SlugField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = [
|
||||
'name', 'slug', 'description',
|
||||
]
|
||||
fields = (
|
||||
'name', 'slug', 'description', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ClusterGroupForm(BootstrapMixin, CustomFieldModelForm):
|
||||
slug = SlugField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = [
|
||||
'name', 'slug', 'description',
|
||||
]
|
||||
fields = (
|
||||
'name', 'slug', 'description', 'tags',
|
||||
)
|
||||
|
||||
|
||||
class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
|
||||
|
25
netbox/virtualization/migrations/0025_extend_tag_support.py
Normal file
25
netbox/virtualization/migrations/0025_extend_tag_support.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-21 14:50
|
||||
|
||||
from django.db import migrations
|
||||
import taggit.managers
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('extras', '0062_clear_secrets_changelog'),
|
||||
('virtualization', '0024_cluster_relax_uniqueness'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='clustergroup',
|
||||
name='tags',
|
||||
field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='clustertype',
|
||||
name='tags',
|
||||
field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
|
||||
),
|
||||
]
|
@@ -30,7 +30,7 @@ __all__ = (
|
||||
# Cluster types
|
||||
#
|
||||
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||
class ClusterType(OrganizationalModel):
|
||||
"""
|
||||
A type of Cluster.
|
||||
@@ -64,7 +64,7 @@ class ClusterType(OrganizationalModel):
|
||||
# Cluster groups
|
||||
#
|
||||
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||
class ClusterGroup(OrganizationalModel):
|
||||
"""
|
||||
An organizational group of Clusters.
|
||||
|
@@ -40,11 +40,14 @@ class ClusterTypeTable(BaseTable):
|
||||
cluster_count = tables.Column(
|
||||
verbose_name='Clusters'
|
||||
)
|
||||
tags = TagColumn(
|
||||
url_name='virtualization:clustertype_list'
|
||||
)
|
||||
actions = ButtonsColumn(ClusterType)
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = ClusterType
|
||||
fields = ('pk', 'name', 'slug', 'cluster_count', 'description', 'actions')
|
||||
fields = ('pk', 'name', 'slug', 'cluster_count', 'description', 'tags', 'actions')
|
||||
default_columns = ('pk', 'name', 'cluster_count', 'description', 'actions')
|
||||
|
||||
|
||||
@@ -60,11 +63,14 @@ class ClusterGroupTable(BaseTable):
|
||||
cluster_count = tables.Column(
|
||||
verbose_name='Clusters'
|
||||
)
|
||||
tags = TagColumn(
|
||||
url_name='virtualization:clustergroup_list'
|
||||
)
|
||||
actions = ButtonsColumn(ClusterGroup)
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = ClusterGroup
|
||||
fields = ('pk', 'name', 'slug', 'cluster_count', 'description', 'actions')
|
||||
fields = ('pk', 'name', 'slug', 'cluster_count', 'description', 'tags', 'actions')
|
||||
default_columns = ('pk', 'name', 'cluster_count', 'description', 'actions')
|
||||
|
||||
|
||||
|
@@ -22,10 +22,13 @@ class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
ClusterGroup(name='Cluster Group 3', slug='cluster-group-3'),
|
||||
])
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'name': 'Cluster Group X',
|
||||
'slug': 'cluster-group-x',
|
||||
'description': 'A new cluster group',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
@@ -52,10 +55,13 @@ class ClusterTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
ClusterType(name='Cluster Type 3', slug='cluster-type-3'),
|
||||
])
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'name': 'Cluster Type X',
|
||||
'slug': 'cluster-type-x',
|
||||
'description': 'A new cluster type',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
|
Reference in New Issue
Block a user