diff --git a/netbox/circuits/api/serializers_/circuits.py b/netbox/circuits/api/serializers_/circuits.py index 42e639954..9eed14c11 100644 --- a/netbox/circuits/api/serializers_/circuits.py +++ b/netbox/circuits/api/serializers_/circuits.py @@ -45,6 +45,34 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer): ] +class CircuitGroupSerializer(NetBoxModelSerializer): + tenant = TenantSerializer(nested=True, required=False, allow_null=True) + circuit_count = RelatedObjectCountField('assignments') + + class Meta: + model = CircuitGroup + fields = [ + 'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tenant', + 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count' + ] + brief_fields = ('id', 'url', 'display', 'name') + + +class CircuitGroupAssignmentSerializer_(NetBoxModelSerializer): + """ + Base serializer for group assignments under CircuitSerializer. + """ + group = CircuitGroupSerializer(nested=True) + priority = ChoiceField(choices=CircuitPriorityChoices, allow_blank=True, required=False) + + class Meta: + model = CircuitGroupAssignment + fields = [ + 'id', 'url', 'display_url', 'display', 'group', 'priority', 'tags', 'created', 'last_updated', + ] + brief_fields = ('id', 'url', 'display', 'group', 'priority') + + class CircuitSerializer(NetBoxModelSerializer): provider = ProviderSerializer(nested=True) provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True, default=None) @@ -53,13 +81,14 @@ class CircuitSerializer(NetBoxModelSerializer): tenant = TenantSerializer(nested=True, required=False, allow_null=True) termination_a = CircuitCircuitTerminationSerializer(read_only=True, allow_null=True) termination_z = CircuitCircuitTerminationSerializer(read_only=True, allow_null=True) + assignments = CircuitGroupAssignmentSerializer_(nested=True, many=True, required=False) class Meta: model = Circuit fields = [ 'id', 'url', 'display_url', 'display', 'cid', 'provider', 'provider_account', 'type', 'status', 'tenant', 'install_date', 'termination_date', 'commit_rate', 'description', 'termination_a', 'termination_z', - 'comments', 'tags', 'custom_fields', 'created', 'last_updated', + 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'assignments', ] brief_fields = ('id', 'url', 'display', 'cid', 'description') @@ -79,29 +108,12 @@ class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer brief_fields = ('id', 'url', 'display', 'circuit', 'term_side', 'description', 'cable', '_occupied') -class CircuitGroupSerializer(NetBoxModelSerializer): - # Related object counts - circuit_group_assignment_count = RelatedObjectCountField('assignments') - tenant = TenantSerializer(nested=True, required=False, allow_null=True) - - class Meta: - model = CircuitGroup - fields = [ - 'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tenant', - 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_group_assignment_count' - ] - brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'circuit_group_assignment_count') - - -class CircuitGroupAssignmentSerializer(NetBoxModelSerializer): - group = CircuitGroupSerializer(nested=True) +class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_): circuit = CircuitSerializer(nested=True) - priority = ChoiceField(choices=CircuitPriorityChoices, allow_blank=True, required=False) class Meta: model = CircuitGroupAssignment fields = [ - 'id', 'url', 'display_url', 'display', 'group', 'circuit', 'priority', - 'tags', 'created', 'last_updated', + 'id', 'url', 'display_url', 'display', 'group', 'circuit', 'priority', 'tags', 'created', 'last_updated', ] brief_fields = ('id', 'url', 'display', 'group', 'circuit', 'priority') diff --git a/netbox/circuits/migrations/0044_circuitgroup_circuitgroupassignment_and_more.py b/netbox/circuits/migrations/0044_circuitgroup_circuitgroupassignment_and_more.py index 7a6d1365f..40ea5bd1e 100644 --- a/netbox/circuits/migrations/0044_circuitgroup_circuitgroupassignment_and_more.py +++ b/netbox/circuits/migrations/0044_circuitgroup_circuitgroupassignment_and_more.py @@ -84,7 +84,7 @@ class Migration(migrations.Migration): migrations.AddConstraint( model_name='circuitgroupassignment', constraint=models.UniqueConstraint( - fields=('circuit', 'group'), name='circuits_circuitgroupassignment_unique_circuit_assignment' + fields=('circuit', 'group'), name='circuits_circuitgroupassignment_unique_circuit_group' ), ), ] diff --git a/netbox/circuits/models/circuits.py b/netbox/circuits/models/circuits.py index e9143c362..7c5e5f2b5 100644 --- a/netbox/circuits/models/circuits.py +++ b/netbox/circuits/models/circuits.py @@ -11,8 +11,8 @@ from utilities.fields import ColorField __all__ = ( 'Circuit', - 'CircuitGroupAssignment', 'CircuitGroup', + 'CircuitGroupAssignment', 'CircuitTermination', 'CircuitType', ) @@ -155,7 +155,7 @@ class Circuit(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): class CircuitGroup(OrganizationalModel): """ - An arbitrary collection of Circuits. + An administrative grouping of Circuits. """ tenant = models.ForeignKey( to='tenancy.Tenant', @@ -167,8 +167,8 @@ class CircuitGroup(OrganizationalModel): class Meta: ordering = ('name',) - verbose_name = _('Circuit group') - verbose_name_plural = _('Circuit group') + verbose_name = _('circuit group') + verbose_name_plural = _('circuit groups') def __str__(self): return self.name @@ -206,8 +206,8 @@ class CircuitGroupAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ordering = ('circuit', 'priority', 'pk') constraints = ( models.UniqueConstraint( - fields=('circuit', 'group',), - name='%(app_label)s_%(class)s_unique_circuit_assignment' + fields=('circuit', 'group'), + name='%(app_label)s_%(class)s_unique_circuit_group' ), ) verbose_name = _('Circuit group assignment') @@ -215,8 +215,8 @@ class CircuitGroupAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, def __str__(self): if self.priority: - return f"{self.group} ({self.get_priority_display()}) -> {self.circuit}" - return str(f"{self.group} -> {self.circuit}") + return f"{self.group} ({self.get_priority_display()})" + return str(self.group) def get_absolute_url(self): return reverse('circuits:circuitgroupassignment', args=[self.pk]) diff --git a/netbox/circuits/tables/circuits.py b/netbox/circuits/tables/circuits.py index d493217b9..3145df43e 100644 --- a/netbox/circuits/tables/circuits.py +++ b/netbox/circuits/tables/circuits.py @@ -158,6 +158,9 @@ class CircuitGroupAssignmentTable(NetBoxTable): priority = tables.Column( verbose_name=_('Priority'), ) + tags = columns.TagColumn( + url_name='circuits:circuitgroupassignment_list' + ) class Meta(NetBoxTable.Meta): model = CircuitGroupAssignment diff --git a/netbox/circuits/tests/test_api.py b/netbox/circuits/tests/test_api.py index 41f621cf8..a3c5cada9 100644 --- a/netbox/circuits/tests/test_api.py +++ b/netbox/circuits/tests/test_api.py @@ -208,7 +208,7 @@ class CircuitTerminationTest(APIViewTestCases.APIViewTestCase): class CircuitGroupTest(APIViewTestCases.APIViewTestCase): model = CircuitGroup - brief_fields = ['circuit_group_assignment_count', 'description', 'display', 'id', 'name', 'slug', 'url'] + brief_fields = ['display', 'id', 'name', 'url'] bulk_update_data = { 'description': 'New description', } diff --git a/netbox/circuits/tests/test_filtersets.py b/netbox/circuits/tests/test_filtersets.py index a6d4e0e5a..3d0f3f5aa 100644 --- a/netbox/circuits/tests/test_filtersets.py +++ b/netbox/circuits/tests/test_filtersets.py @@ -558,10 +558,7 @@ class CircuitGroupAssignmentTestCase(TestCase, ChangeLoggedFilterSetTests): groups = CircuitGroup.objects.filter(name__in=['Circuit Group 1', 'Circuit Group 2']) params = {'group_id': [groups[0].pk, groups[1].pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - - def test_circuit_group_slug(self): - groups = CircuitGroup.objects.filter(slug__in=['circuit-group-1', 'circuit-group-2']) - params = {'group_id': [groups[0].pk, groups[1].pk]} + params = {'group': [groups[0].slug, groups[1].slug]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_circuit_id(self): diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py index 73b681bab..44f212f9c 100644 --- a/netbox/netbox/navigation/menu.py +++ b/netbox/netbox/navigation/menu.py @@ -259,9 +259,9 @@ CIRCUITS_MENU = Menu( items=( get_model_item('circuits', 'circuit', _('Circuits')), get_model_item('circuits', 'circuittype', _('Circuit Types')), - get_model_item('circuits', 'circuittermination', _('Circuit Terminations')), get_model_item('circuits', 'circuitgroup', _('Circuit Groups')), - get_model_item('circuits', 'circuitgroupassignment', _('Circuit Group Assignments')), + get_model_item('circuits', 'circuitgroupassignment', _('Group Assignments')), + get_model_item('circuits', 'circuittermination', _('Circuit Terminations')), ), ), MenuGroup( diff --git a/netbox/templates/circuits/circuitgroup.html b/netbox/templates/circuits/circuitgroup.html index 01c719a6b..24002f59b 100644 --- a/netbox/templates/circuits/circuitgroup.html +++ b/netbox/templates/circuits/circuitgroup.html @@ -13,7 +13,7 @@ {% block extra_controls %} {% if perms.circuit.add_circuitgroupassignment %} - {% trans "Add Circuit Assignment" %} + {% trans "Assign Circuit" %} {% endif %} {% endblock extra_controls %} diff --git a/netbox/templates/circuits/circuitgroupassignment.html b/netbox/templates/circuits/circuitgroupassignment.html index aadc6c86e..870e46be8 100644 --- a/netbox/templates/circuits/circuitgroupassignment.html +++ b/netbox/templates/circuits/circuitgroupassignment.html @@ -7,7 +7,9 @@ {% block breadcrumbs %} {{ block.super }} - + {% endblock %} {% block content %} @@ -34,5 +36,13 @@ {% include 'inc/panels/custom_fields.html' %} {% plugin_left_page object %} +
+ {% plugin_right_page object %} +
+ +
+
+ {% plugin_full_width_page object %} +
{% endblock %}