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:
@@ -2,7 +2,7 @@ from django.contrib.auth.models import ContentType
|
||||
from rest_framework import serializers
|
||||
|
||||
from netbox.api import ChoiceField, ContentTypeField
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, PrimaryModelSerializer
|
||||
from tenancy.choices import ContactPriorityChoices
|
||||
from tenancy.models import *
|
||||
from .nested_serializers import *
|
||||
@@ -20,8 +20,8 @@ class TenantGroupSerializer(NestedGroupModelSerializer):
|
||||
class Meta:
|
||||
model = TenantGroup
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'custom_fields', 'created', 'last_updated',
|
||||
'tenant_count', '_depth',
|
||||
'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created',
|
||||
'last_updated', 'tenant_count', '_depth',
|
||||
]
|
||||
|
||||
|
||||
@@ -60,18 +60,18 @@ class ContactGroupSerializer(NestedGroupModelSerializer):
|
||||
class Meta:
|
||||
model = ContactGroup
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'custom_fields', 'created', 'last_updated',
|
||||
'contact_count', '_depth',
|
||||
'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created',
|
||||
'last_updated', 'contact_count', '_depth',
|
||||
]
|
||||
|
||||
|
||||
class ContactRoleSerializer(OrganizationalModelSerializer):
|
||||
class ContactRoleSerializer(PrimaryModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactrole-detail')
|
||||
|
||||
class Meta:
|
||||
model = ContactRole
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'custom_fields', 'created', 'last_updated',
|
||||
'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
|
||||
|
||||
|
@@ -30,7 +30,7 @@ class TenantGroupViewSet(CustomFieldModelViewSet):
|
||||
'group',
|
||||
'tenant_count',
|
||||
cumulative=True
|
||||
)
|
||||
).prefetch_related('tags')
|
||||
serializer_class = serializers.TenantGroupSerializer
|
||||
filterset_class = filtersets.TenantGroupFilterSet
|
||||
|
||||
@@ -64,28 +64,24 @@ class ContactGroupViewSet(CustomFieldModelViewSet):
|
||||
'group',
|
||||
'contact_count',
|
||||
cumulative=True
|
||||
)
|
||||
).prefetch_related('tags')
|
||||
serializer_class = serializers.ContactGroupSerializer
|
||||
filterset_class = filtersets.ContactGroupFilterSet
|
||||
|
||||
|
||||
class ContactRoleViewSet(CustomFieldModelViewSet):
|
||||
queryset = ContactRole.objects.all()
|
||||
queryset = ContactRole.objects.prefetch_related('tags')
|
||||
serializer_class = serializers.ContactRoleSerializer
|
||||
filterset_class = filtersets.ContactRoleFilterSet
|
||||
|
||||
|
||||
class ContactViewSet(CustomFieldModelViewSet):
|
||||
queryset = Contact.objects.prefetch_related(
|
||||
'group', 'tags'
|
||||
)
|
||||
queryset = Contact.objects.prefetch_related('group', 'tags')
|
||||
serializer_class = serializers.ContactSerializer
|
||||
filterset_class = filtersets.ContactFilterSet
|
||||
|
||||
|
||||
class ContactAssignmentViewSet(CustomFieldModelViewSet):
|
||||
queryset = ContactAssignment.objects.prefetch_related(
|
||||
'contact', 'role'
|
||||
)
|
||||
queryset = ContactAssignment.objects.prefetch_related('contact', 'role')
|
||||
serializer_class = serializers.ContactAssignmentSerializer
|
||||
filterset_class = filtersets.ContactAssignmentFilterSet
|
||||
|
@@ -17,7 +17,7 @@ __all__ = (
|
||||
# Tenants
|
||||
#
|
||||
|
||||
class TenantGroupBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
class TenantGroupBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=TenantGroup.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -55,7 +55,7 @@ class TenantBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulk
|
||||
# Contacts
|
||||
#
|
||||
|
||||
class ContactGroupBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
class ContactGroupBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ContactGroup.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
@@ -73,7 +73,7 @@ class ContactGroupBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
nullable_fields = ['parent', 'description']
|
||||
|
||||
|
||||
class ContactRoleBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm):
|
||||
class ContactRoleBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=ContactRole.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
|
@@ -28,11 +28,15 @@ class TenantGroupForm(BootstrapMixin, CustomFieldModelForm):
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = TenantGroup
|
||||
fields = [
|
||||
'parent', 'name', 'slug', 'description',
|
||||
'parent', 'name', 'slug', 'description', 'tags',
|
||||
]
|
||||
|
||||
|
||||
@@ -68,18 +72,26 @@ class ContactGroupForm(BootstrapMixin, CustomFieldModelForm):
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ContactGroup
|
||||
fields = ['parent', 'name', 'slug', 'description']
|
||||
fields = ('parent', 'name', 'slug', 'description', 'tags')
|
||||
|
||||
|
||||
class ContactRoleForm(BootstrapMixin, CustomFieldModelForm):
|
||||
slug = SlugField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ContactRole
|
||||
fields = ['name', 'slug', 'description']
|
||||
fields = ('name', 'slug', 'description', 'tags')
|
||||
|
||||
|
||||
class ContactForm(BootstrapMixin, CustomFieldModelForm):
|
||||
|
30
netbox/tenancy/migrations/0004_extend_tag_support.py
Normal file
30
netbox/tenancy/migrations/0004_extend_tag_support.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# 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'),
|
||||
('tenancy', '0003_contacts'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='contactgroup',
|
||||
name='tags',
|
||||
field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contactrole',
|
||||
name='tags',
|
||||
field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tenantgroup',
|
||||
name='tags',
|
||||
field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
|
||||
),
|
||||
]
|
@@ -24,7 +24,7 @@ __all__ = (
|
||||
# Tenants
|
||||
#
|
||||
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||
class TenantGroup(NestedGroupModel):
|
||||
"""
|
||||
An arbitrary collection of Tenants.
|
||||
@@ -111,7 +111,7 @@ class Tenant(PrimaryModel):
|
||||
# Contacts
|
||||
#
|
||||
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||
class ContactGroup(NestedGroupModel):
|
||||
"""
|
||||
An arbitrary collection of Contacts.
|
||||
@@ -145,7 +145,7 @@ class ContactGroup(NestedGroupModel):
|
||||
return reverse('tenancy:contactgroup', args=[self.pk])
|
||||
|
||||
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||
class ContactRole(OrganizationalModel):
|
||||
"""
|
||||
Functional role for a Contact assigned to an object.
|
||||
|
@@ -55,11 +55,14 @@ class TenantGroupTable(BaseTable):
|
||||
url_params={'group_id': 'pk'},
|
||||
verbose_name='Tenants'
|
||||
)
|
||||
tags = TagColumn(
|
||||
url_name='tenancy:tenantgroup_list'
|
||||
)
|
||||
actions = ButtonsColumn(TenantGroup)
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = TenantGroup
|
||||
fields = ('pk', 'name', 'tenant_count', 'description', 'slug', 'actions')
|
||||
fields = ('pk', 'name', 'tenant_count', 'description', 'slug', 'tags', 'actions')
|
||||
default_columns = ('pk', 'name', 'tenant_count', 'description', 'actions')
|
||||
|
||||
|
||||
@@ -96,11 +99,14 @@ class ContactGroupTable(BaseTable):
|
||||
url_params={'role_id': 'pk'},
|
||||
verbose_name='Contacts'
|
||||
)
|
||||
tags = TagColumn(
|
||||
url_name='tenancy:contactgroup_list'
|
||||
)
|
||||
actions = ButtonsColumn(ContactGroup)
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = ContactGroup
|
||||
fields = ('pk', 'name', 'contact_count', 'description', 'slug', 'actions')
|
||||
fields = ('pk', 'name', 'contact_count', 'description', 'slug', 'tags', 'actions')
|
||||
default_columns = ('pk', 'name', 'contact_count', 'description', 'actions')
|
||||
|
||||
|
||||
|
@@ -16,10 +16,13 @@ class TenantGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
for tenanantgroup in tenant_groups:
|
||||
tenanantgroup.save()
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'name': 'Tenant Group X',
|
||||
'slug': 'tenant-group-x',
|
||||
'description': 'A new tenant group',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
@@ -90,10 +93,13 @@ class ContactGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
for tenanantgroup in contact_groups:
|
||||
tenanantgroup.save()
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'name': 'Contact Group X',
|
||||
'slug': 'contact-group-x',
|
||||
'description': 'A new contact group',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
@@ -120,10 +126,13 @@ class ContactRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
ContactRole(name='Contact Role 3', slug='contact-role-3'),
|
||||
])
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'name': 'Devie Role X',
|
||||
'slug': 'contact-role-x',
|
||||
'description': 'New contact role',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
|
Reference in New Issue
Block a user