diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index aee729945..5e0a484f8 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -16,6 +16,7 @@ from extras.utils import FeatureQuery from netbox.api.exceptions import SerializerNotFound from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField from netbox.api.serializers import BaseModelSerializer, NetBoxModelSerializer, ValidatedModelSerializer +from netbox.api.serializers.features import TaggableModelSerializer from netbox.constants import NESTED_SERIALIZER_PREFIX from tenancy.api.nested_serializers import NestedTenantSerializer, NestedTenantGroupSerializer from tenancy.models import Tenant, TenantGroup @@ -29,6 +30,7 @@ from .nested_serializers import * __all__ = ( 'ConfigContextSerializer', + 'ConfigTemplateSerializer', 'ContentTypeSerializer', 'CustomFieldSerializer', 'CustomLinkSerializer', @@ -387,7 +389,7 @@ class ConfigContextSerializer(ValidatedModelSerializer): # Config templates # -class ConfigTemplateSerializer(ValidatedModelSerializer): +class ConfigTemplateSerializer(TaggableModelSerializer, ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:configtemplate-detail') data_source = NestedDataSourceSerializer( required=False @@ -400,7 +402,7 @@ class ConfigTemplateSerializer(ValidatedModelSerializer): model = ConfigTemplate fields = [ 'id', 'url', 'display', 'name', 'description', 'environment_params', 'template_code', 'data_source', - 'data_path', 'data_file', 'data_synced', 'created', 'last_updated', + 'data_path', 'data_file', 'data_synced', 'tags', 'created', 'last_updated', ] diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index 38c828916..816406647 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -11,6 +11,7 @@ from tenancy.models import Tenant, TenantGroup from utilities.filters import ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter from virtualization.models import Cluster, ClusterGroup, ClusterType from .choices import * +from .filters import TagFilter from .models import * __all__ = ( @@ -467,6 +468,7 @@ class ConfigTemplateFilterSet(BaseFilterSet): queryset=DataSource.objects.all(), label=_('Data file (ID)'), ) + tag = TagFilter() class Meta: model = ConfigTemplate diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 1998170b0..b035c2579 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -89,7 +89,7 @@ class ConfigTemplateImportForm(CSVModelForm): class Meta: model = ConfigTemplate fields = ( - 'name', 'description', 'environment_params', 'template_code', + 'name', 'description', 'environment_params', 'template_code', 'tags', ) diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py index c77f334f9..c3609f98b 100644 --- a/netbox/extras/forms/filtersets.py +++ b/netbox/extras/forms/filtersets.py @@ -367,7 +367,7 @@ class ConfigContextFilterForm(SavedFiltersMixin, FilterForm): class ConfigTemplateFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( - (None, ('q', 'filter_id')), + (None, ('q', 'filter_id', 'tag')), ('Data', ('data_source_id', 'data_file_id')), ) data_source_id = DynamicModelMultipleChoiceField( @@ -383,6 +383,7 @@ class ConfigTemplateFilterForm(SavedFiltersMixin, FilterForm): 'source_id': '$data_source_id' } ) + tag = TagFilterField(ConfigTemplate) class LocalConfigContextFilterForm(forms.Form): diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index bb9430616..4ce81c01b 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -281,7 +281,7 @@ class ConfigTemplateForm(BootstrapMixin, SyncedDataMixin, forms.ModelForm): ) fieldsets = ( - ('Export Template', ('name', 'description', 'environment_params', 'tags')), + ('Config Template', ('name', 'description', 'environment_params', 'tags')), ('Content', ('data_source', 'data_file', 'template_code',)), ) diff --git a/netbox/extras/migrations/0086_configtemplate.py b/netbox/extras/migrations/0086_configtemplate.py index 4dbc88f9f..bd47254e9 100644 --- a/netbox/extras/migrations/0086_configtemplate.py +++ b/netbox/extras/migrations/0086_configtemplate.py @@ -1,7 +1,6 @@ -# Generated by Django 4.1.6 on 2023-02-09 19:33 - from django.db import migrations, models import django.db.models.deletion +import taggit.managers class Migration(migrations.Migration): @@ -26,6 +25,7 @@ class Migration(migrations.Migration): ('environment_params', models.JSONField(blank=True, null=True)), ('data_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile')), ('data_source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource')), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ 'ordering': ('name',), diff --git a/netbox/extras/models/configs.py b/netbox/extras/models/configs.py index d1c90b446..5fd068245 100644 --- a/netbox/extras/models/configs.py +++ b/netbox/extras/models/configs.py @@ -9,7 +9,7 @@ from jinja2.sandbox import SandboxedEnvironment from extras.querysets import ConfigContextQuerySet from netbox.config import get_config from netbox.models import ChangeLoggedModel -from netbox.models.features import ExportTemplatesMixin, SyncedDataMixin +from netbox.models.features import ExportTemplatesMixin, SyncedDataMixin, TagsMixin from utilities.jinja2 import ConfigTemplateLoader from utilities.utils import deepmerge @@ -193,7 +193,7 @@ class ConfigContextModel(models.Model): # Config templates # -class ConfigTemplate(SyncedDataMixin, ExportTemplatesMixin, ChangeLoggedModel): +class ConfigTemplate(SyncedDataMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel): name = models.CharField( max_length=100 ) diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index b4c584188..5991203f2 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -237,11 +237,15 @@ class ConfigTemplateTable(NetBoxTable): is_synced = columns.BooleanColumn( verbose_name='Synced' ) + tags = columns.TagColumn( + url_name='extras:configtemplate_list' + ) class Meta(NetBoxTable.Meta): model = ConfigTemplate fields = ( 'pk', 'id', 'name', 'description', 'data_source', 'data_file', 'data_synced', 'created', 'last_updated', + 'tags', ) default_columns = ( 'pk', 'name', 'description', 'is_synced', diff --git a/netbox/templates/extras/configtemplate.html b/netbox/templates/extras/configtemplate.html index 57178acb9..937789ee2 100644 --- a/netbox/templates/extras/configtemplate.html +++ b/netbox/templates/extras/configtemplate.html @@ -49,6 +49,7 @@ + {% include 'inc/panels/tags.html' %} {% plugin_left_page object %}