diff --git a/netbox/circuits/filtersets.py b/netbox/circuits/filtersets.py index a7471cb62..21b12fc94 100644 --- a/netbox/circuits/filtersets.py +++ b/netbox/circuits/filtersets.py @@ -173,7 +173,7 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte label=_('Provider account (account)'), ) provider_network_id = django_filters.ModelMultipleChoiceFilter( - field_name='terminations__provider_network', + field_name='terminations___provider_network', queryset=ProviderNetwork.objects.all(), label=_('Provider network (ID)'), ) @@ -316,6 +316,7 @@ class CircuitTerminationFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet): ) provider_network_id = django_filters.ModelMultipleChoiceFilter( queryset=ProviderNetwork.objects.all(), + field_name='_provider_network', label=_('ProviderNetwork (ID)'), ) provider_id = django_filters.ModelMultipleChoiceFilter( diff --git a/netbox/circuits/forms/bulk_edit.py b/netbox/circuits/forms/bulk_edit.py index 39709387f..be1cd9790 100644 --- a/netbox/circuits/forms/bulk_edit.py +++ b/netbox/circuits/forms/bulk_edit.py @@ -12,7 +12,7 @@ from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import add_blank_choice, get_field_value from utilities.forms.fields import ColorField, CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField -from utilities.forms.rendering import FieldSet, TabbedGroups +from utilities.forms.rendering import FieldSet from utilities.forms.widgets import BulkEditNullBooleanSelect, DatePicker, HTMXSelect, NumberWithOptions __all__ = ( @@ -212,11 +212,6 @@ class CircuitTerminationBulkEditForm(NetBoxModelBulkEditForm): disabled=True, selector=True ) - provider_network = DynamicModelChoiceField( - label=_('Provider Network'), - queryset=ProviderNetwork.objects.all(), - required=False - ) port_speed = forms.IntegerField( required=False, label=_('Port speed (Kbps)'), @@ -235,10 +230,7 @@ class CircuitTerminationBulkEditForm(NetBoxModelBulkEditForm): fieldsets = ( FieldSet( 'description', - TabbedGroups( - FieldSet('scope_type', 'scope', name=_('Scope')), - FieldSet('provider_network', name=_('Provider Network')), - ), + FieldSet('scope_type', 'scope', name=_('Scope')), 'mark_connected', name=_('Circuit Termination') ), FieldSet('port_speed', 'upstream_speed', name=_('Termination Details')), diff --git a/netbox/circuits/forms/bulk_import.py b/netbox/circuits/forms/bulk_import.py index a7a2f39d1..87b1e840e 100644 --- a/netbox/circuits/forms/bulk_import.py +++ b/netbox/circuits/forms/bulk_import.py @@ -133,19 +133,13 @@ class BaseCircuitTerminationImportForm(forms.ModelForm): required=False, label=_('Scope type (app & model)') ) - provider_network = CSVModelChoiceField( - label=_('Provider network'), - queryset=ProviderNetwork.objects.all(), - to_field_name='name', - required=False - ) class CircuitTerminationImportRelatedForm(BaseCircuitTerminationImportForm): class Meta: model = CircuitTermination fields = [ - 'circuit', 'term_side', 'scope_type', 'scope_id', 'provider_network', 'port_speed', 'upstream_speed', 'xconnect_id', + 'circuit', 'term_side', 'scope_type', 'scope_id', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description' ] labels = { @@ -158,7 +152,7 @@ class CircuitTerminationImportForm(NetBoxModelImportForm, BaseCircuitTermination class Meta: model = CircuitTermination fields = [ - 'circuit', 'term_side', 'scope_type', 'scope_id', 'provider_network', 'port_speed', 'upstream_speed', 'xconnect_id', + 'circuit', 'term_side', 'scope_type', 'scope_id', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags' ] labels = { diff --git a/netbox/circuits/forms/filtersets.py b/netbox/circuits/forms/filtersets.py index ab1215765..1bbd4ee3b 100644 --- a/netbox/circuits/forms/filtersets.py +++ b/netbox/circuits/forms/filtersets.py @@ -207,7 +207,7 @@ class CircuitTerminationFilterForm(NetBoxModelFilterSetForm): fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('circuit_id', 'term_side', name=_('Circuit')), - FieldSet('provider_id', 'provider_network_id', name=_('Provider')), + FieldSet('provider_id', name=_('Provider')), FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Scope')), ) region_id = DynamicModelMultipleChoiceField( diff --git a/netbox/circuits/forms/model_forms.py b/netbox/circuits/forms/model_forms.py index 9988a6ff1..1240cae26 100644 --- a/netbox/circuits/forms/model_forms.py +++ b/netbox/circuits/forms/model_forms.py @@ -11,7 +11,7 @@ from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms import get_field_value from utilities.forms.fields import CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField -from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups +from utilities.forms.rendering import FieldSet, InlineFields from utilities.forms.widgets import DatePicker, HTMXSelect, NumberWithOptions from utilities.templatetags.builtins.filters import bettertitle @@ -162,20 +162,11 @@ class CircuitTerminationForm(NetBoxModelForm): disabled=True, selector=True ) - provider_network = DynamicModelChoiceField( - label=_('Provider network'), - queryset=ProviderNetwork.objects.all(), - required=False, - selector=True - ) fieldsets = ( FieldSet( 'circuit', 'term_side', 'description', 'tags', - TabbedGroups( - FieldSet('scope_type', 'scope', name=_('Scope')), - FieldSet('provider_network', name=_('Provider Network')), - ), + FieldSet('scope_type', 'scope', name=_('Scope')), 'mark_connected', name=_('Circuit Termination') ), FieldSet('port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', name=_('Termination Details')), @@ -184,7 +175,7 @@ class CircuitTerminationForm(NetBoxModelForm): class Meta: model = CircuitTermination fields = [ - 'circuit', 'term_side', 'scope_type', 'provider_network', 'mark_connected', 'port_speed', 'upstream_speed', + 'circuit', 'term_side', 'scope_type', 'mark_connected', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags', ] widgets = { diff --git a/netbox/circuits/graphql/types.py b/netbox/circuits/graphql/types.py index f841277a1..788664462 100644 --- a/netbox/circuits/graphql/types.py +++ b/netbox/circuits/graphql/types.py @@ -64,7 +64,6 @@ class ProviderNetworkType(NetBoxObjectType): ) class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, ObjectType): circuit: Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')] - provider_network: Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')] | None @strawberry_django.field def scope(self) -> Annotated[Union[ @@ -72,6 +71,7 @@ class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, Ob Annotated["RegionType", strawberry.lazy('dcim.graphql.types')], Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')], Annotated["SiteType", strawberry.lazy('dcim.graphql.types')], + Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')], ], strawberry.union("CircuitTerminationScopeType")] | None: return self.scope diff --git a/netbox/circuits/migrations/0047_circuittermination__scope.py b/netbox/circuits/migrations/0047_circuittermination__scope.py index 8c87f397e..26d28ba74 100644 --- a/netbox/circuits/migrations/0047_circuittermination__scope.py +++ b/netbox/circuits/migrations/0047_circuittermination__scope.py @@ -42,6 +42,11 @@ class Migration(migrations.Migration): to='contenttypes.contenttype', ), ), + migrations.RenameField( + model_name='circuittermination', + old_name='provider_network', + new_name='_provider_network', + ), # Copy over existing site assignments migrations.RunPython( diff --git a/netbox/circuits/models/circuits.py b/netbox/circuits/models/circuits.py index 9eed05ca4..6c1427ac7 100644 --- a/netbox/circuits/models/circuits.py +++ b/netbox/circuits/models/circuits.py @@ -252,13 +252,6 @@ class CircuitTermination( ct_field='scope_type', fk_field='scope_id' ) - provider_network = models.ForeignKey( - to='circuits.ProviderNetwork', - on_delete=models.PROTECT, - related_name='circuit_terminations', - blank=True, - null=True - ) port_speed = models.PositiveIntegerField( verbose_name=_('port speed (Kbps)'), blank=True, @@ -290,6 +283,13 @@ class CircuitTermination( ) # Cached associations to enable efficient filtering + _provider_network = models.ForeignKey( + to='circuits.ProviderNetwork', + on_delete=models.PROTECT, + related_name='circuit_terminations', + blank=True, + null=True + ) _location = models.ForeignKey( to='dcim.Location', on_delete=models.CASCADE, @@ -352,7 +352,7 @@ class CircuitTermination( super().save(*args, **kwargs) def cache_related_objects(self): - self._region = self._sitegroup = self._site = self._location = None + self._provider_network = self._region = self._sitegroup = self._site = self._location = None if self.scope_type: scope_type = self.scope_type.model_class() if scope_type == apps.get_model('dcim', 'region'): @@ -368,6 +368,8 @@ class CircuitTermination( self._sitegroup = self.scope.site.group self._site = self.scope.site self._location = self.scope + elif scope_type == apps.get_model('circuits', 'providernetwork'): + self._provider_network = self.scope cache_related_objects.alters_data = True def to_objectchange(self, action):