diff --git a/docs/plugins/development/forms.md b/docs/plugins/development/forms.md new file mode 100644 index 000000000..5af178194 --- /dev/null +++ b/docs/plugins/development/forms.md @@ -0,0 +1,10 @@ +# Forms + +NetBox provides several base form classes for use by plugins. These are documented below. + +* `NetBoxModelForm` +* `NetBoxModelCSVForm` +* `NetBoxModelBulkEditForm` +* `NetBoxModelFilterSetForm` + +### TODO: Include forms reference diff --git a/mkdocs.yml b/mkdocs.yml index 3b1e52f50..004f21c5e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -105,6 +105,7 @@ nav: - Models: 'plugins/development/models.md' - Views: 'plugins/development/views.md' - Tables: 'plugins/development/tables.md' + - Forms: 'plugins/development/forms.md' - Filter Sets: 'plugins/development/filtersets.md' - REST API: 'plugins/development/rest-api.md' - Background Tasks: 'plugins/development/background-tasks.md' diff --git a/netbox/circuits/forms/bulk_edit.py b/netbox/circuits/forms/bulk_edit.py index af6bca91f..3e54cf711 100644 --- a/netbox/circuits/forms/bulk_edit.py +++ b/netbox/circuits/forms/bulk_edit.py @@ -2,7 +2,7 @@ from django import forms from circuits.choices import CircuitStatusChoices from circuits.models import * -from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm +from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import add_blank_choice, CommentField, DynamicModelChoiceField, SmallTextarea, StaticSelect @@ -14,7 +14,7 @@ __all__ = ( ) -class ProviderBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ProviderBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Provider.objects.all(), widget=forms.MultipleHiddenInput @@ -53,7 +53,7 @@ class ProviderBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class ProviderNetworkBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ProviderNetwork.objects.all(), widget=forms.MultipleHiddenInput @@ -81,7 +81,7 @@ class ProviderNetworkBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditFor ] -class CircuitTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class CircuitTypeBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=CircuitType.objects.all(), widget=forms.MultipleHiddenInput @@ -95,7 +95,7 @@ class CircuitTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['description'] -class CircuitBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class CircuitBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Circuit.objects.all(), widget=forms.MultipleHiddenInput diff --git a/netbox/circuits/forms/bulk_import.py b/netbox/circuits/forms/bulk_import.py index fe1b927e5..6da79f75c 100644 --- a/netbox/circuits/forms/bulk_import.py +++ b/netbox/circuits/forms/bulk_import.py @@ -1,6 +1,6 @@ from circuits.choices import CircuitStatusChoices from circuits.models import * -from extras.forms import CustomFieldModelCSVForm +from netbox.forms import NetBoxModelCSVForm from tenancy.models import Tenant from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField @@ -12,7 +12,7 @@ __all__ = ( ) -class ProviderCSVForm(CustomFieldModelCSVForm): +class ProviderCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -22,7 +22,7 @@ class ProviderCSVForm(CustomFieldModelCSVForm): ) -class ProviderNetworkCSVForm(CustomFieldModelCSVForm): +class ProviderNetworkCSVForm(NetBoxModelCSVForm): provider = CSVModelChoiceField( queryset=Provider.objects.all(), to_field_name='name', @@ -36,7 +36,7 @@ class ProviderNetworkCSVForm(CustomFieldModelCSVForm): ] -class CircuitTypeCSVForm(CustomFieldModelCSVForm): +class CircuitTypeCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -47,7 +47,7 @@ class CircuitTypeCSVForm(CustomFieldModelCSVForm): } -class CircuitCSVForm(CustomFieldModelCSVForm): +class CircuitCSVForm(NetBoxModelCSVForm): provider = CSVModelChoiceField( queryset=Provider.objects.all(), to_field_name='name', diff --git a/netbox/circuits/forms/filtersets.py b/netbox/circuits/forms/filtersets.py index f5ff65088..18f914b58 100644 --- a/netbox/circuits/forms/filtersets.py +++ b/netbox/circuits/forms/filtersets.py @@ -4,7 +4,7 @@ from django.utils.translation import gettext as _ from circuits.choices import CircuitStatusChoices from circuits.models import * from dcim.models import Region, Site, SiteGroup -from extras.forms import CustomFieldModelFilterForm +from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import DynamicModelMultipleChoiceField, StaticSelectMultiple, TagFilterField @@ -16,7 +16,7 @@ __all__ = ( ) -class ProviderFilterForm(CustomFieldModelFilterForm): +class ProviderFilterForm(NetBoxModelFilterSetForm): model = Provider field_groups = [ ['q', 'tag'], @@ -49,7 +49,7 @@ class ProviderFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class ProviderNetworkFilterForm(CustomFieldModelFilterForm): +class ProviderNetworkFilterForm(NetBoxModelFilterSetForm): model = ProviderNetwork field_groups = ( ('q', 'tag'), @@ -67,12 +67,12 @@ class ProviderNetworkFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class CircuitTypeFilterForm(CustomFieldModelFilterForm): +class CircuitTypeFilterForm(NetBoxModelFilterSetForm): model = CircuitType tag = TagFilterField(model) -class CircuitFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class CircuitFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Circuit field_groups = [ ['q', 'tag'], diff --git a/netbox/circuits/forms/models.py b/netbox/circuits/forms/models.py index f67114828..bf5d92e85 100644 --- a/netbox/circuits/forms/models.py +++ b/netbox/circuits/forms/models.py @@ -2,8 +2,8 @@ from django import forms from circuits.models import * from dcim.models import Region, Site, SiteGroup -from extras.forms import CustomFieldModelForm from extras.models import Tag +from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms import ( BootstrapMixin, CommentField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, @@ -19,7 +19,7 @@ __all__ = ( ) -class ProviderForm(CustomFieldModelForm): +class ProviderForm(NetBoxModelForm): slug = SlugField() comments = CommentField() tags = DynamicModelMultipleChoiceField( @@ -53,7 +53,7 @@ class ProviderForm(CustomFieldModelForm): } -class ProviderNetworkForm(CustomFieldModelForm): +class ProviderNetworkForm(NetBoxModelForm): provider = DynamicModelChoiceField( queryset=Provider.objects.all() ) @@ -73,7 +73,7 @@ class ProviderNetworkForm(CustomFieldModelForm): ) -class CircuitTypeForm(CustomFieldModelForm): +class CircuitTypeForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -87,7 +87,7 @@ class CircuitTypeForm(CustomFieldModelForm): ] -class CircuitForm(TenancyForm, CustomFieldModelForm): +class CircuitForm(TenancyForm, NetBoxModelForm): provider = DynamicModelChoiceField( queryset=Provider.objects.all() ) diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index 3d73ada47..f5eb179fa 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -6,8 +6,8 @@ from timezone_field import TimeZoneFormField from dcim.choices import * from dcim.constants import * from dcim.models import * -from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm from ipam.models import ASN, VLAN, VRF +from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import ( add_blank_choice, BulkEditForm, BulkEditNullBooleanSelect, ColorField, CommentField, DynamicModelChoiceField, @@ -57,7 +57,7 @@ __all__ = ( ) -class RegionBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RegionBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Region.objects.all(), widget=forms.MultipleHiddenInput @@ -75,7 +75,7 @@ class RegionBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['parent', 'description'] -class SiteGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class SiteGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=SiteGroup.objects.all(), widget=forms.MultipleHiddenInput @@ -93,7 +93,7 @@ class SiteGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['parent', 'description'] -class SiteBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class SiteBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Site.objects.all(), widget=forms.MultipleHiddenInput @@ -137,7 +137,7 @@ class SiteBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class LocationBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class LocationBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Location.objects.all(), widget=forms.MultipleHiddenInput @@ -166,7 +166,7 @@ class LocationBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['parent', 'tenant', 'description'] -class RackRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RackRoleBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=RackRole.objects.all(), widget=forms.MultipleHiddenInput @@ -183,7 +183,7 @@ class RackRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['color', 'description'] -class RackBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RackBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Rack.objects.all(), widget=forms.MultipleHiddenInput @@ -283,7 +283,7 @@ class RackBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class RackReservationBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RackReservationBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=RackReservation.objects.all(), widget=forms.MultipleHiddenInput() @@ -308,7 +308,7 @@ class RackReservationBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditFor nullable_fields = [] -class ManufacturerBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ManufacturerBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Manufacturer.objects.all(), widget=forms.MultipleHiddenInput @@ -322,7 +322,7 @@ class ManufacturerBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['description'] -class DeviceTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=DeviceType.objects.all(), widget=forms.MultipleHiddenInput() @@ -353,7 +353,7 @@ class DeviceTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['part_number', 'airflow'] -class ModuleTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ModuleType.objects.all(), widget=forms.MultipleHiddenInput() @@ -370,7 +370,7 @@ class ModuleTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['part_number'] -class DeviceRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=DeviceRole.objects.all(), widget=forms.MultipleHiddenInput @@ -392,7 +392,7 @@ class DeviceRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['color', 'description'] -class PlatformBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class PlatformBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Platform.objects.all(), widget=forms.MultipleHiddenInput @@ -415,7 +415,7 @@ class PlatformBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['manufacturer', 'napalm_driver', 'description'] -class DeviceBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class DeviceBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Device.objects.all(), widget=forms.MultipleHiddenInput() @@ -476,7 +476,7 @@ class DeviceBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class ModuleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ModuleBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Module.objects.all(), widget=forms.MultipleHiddenInput() @@ -502,7 +502,7 @@ class ModuleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['serial'] -class CableBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class CableBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Cable.objects.all(), widget=forms.MultipleHiddenInput @@ -558,7 +558,7 @@ class CableBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): }) -class VirtualChassisBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class VirtualChassisBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VirtualChassis.objects.all(), widget=forms.MultipleHiddenInput() @@ -572,7 +572,7 @@ class VirtualChassisBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm nullable_fields = ['domain'] -class PowerPanelBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class PowerPanelBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=PowerPanel.objects.all(), widget=forms.MultipleHiddenInput @@ -611,7 +611,7 @@ class PowerPanelBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['location'] -class PowerFeedBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class PowerFeedBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=PowerFeed.objects.all(), widget=forms.MultipleHiddenInput @@ -939,8 +939,7 @@ class InventoryItemTemplateBulkEditForm(BulkEditForm): class ConsolePortBulkEditForm( form_from_model(ConsolePort, ['label', 'type', 'speed', 'mark_connected', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=ConsolePort.objects.all(), @@ -957,8 +956,7 @@ class ConsolePortBulkEditForm( class ConsoleServerPortBulkEditForm( form_from_model(ConsoleServerPort, ['label', 'type', 'speed', 'mark_connected', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=ConsoleServerPort.objects.all(), @@ -975,8 +973,7 @@ class ConsoleServerPortBulkEditForm( class PowerPortBulkEditForm( form_from_model(PowerPort, ['label', 'type', 'maximum_draw', 'allocated_draw', 'mark_connected', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=PowerPort.objects.all(), @@ -993,8 +990,7 @@ class PowerPortBulkEditForm( class PowerOutletBulkEditForm( form_from_model(PowerOutlet, ['label', 'type', 'feed_leg', 'power_port', 'mark_connected', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=PowerOutlet.objects.all(), @@ -1031,8 +1027,7 @@ class InterfaceBulkEditForm( 'label', 'type', 'parent', 'bridge', 'lag', 'speed', 'duplex', 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', ]), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=Interface.objects.all(), @@ -1154,8 +1149,7 @@ class InterfaceBulkEditForm( class FrontPortBulkEditForm( form_from_model(FrontPort, ['label', 'type', 'color', 'mark_connected', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=FrontPort.objects.all(), @@ -1168,8 +1162,7 @@ class FrontPortBulkEditForm( class RearPortBulkEditForm( form_from_model(RearPort, ['label', 'type', 'color', 'mark_connected', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=RearPort.objects.all(), @@ -1182,8 +1175,7 @@ class RearPortBulkEditForm( class ModuleBayBulkEditForm( form_from_model(DeviceBay, ['label', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=ModuleBay.objects.all(), @@ -1196,8 +1188,7 @@ class ModuleBayBulkEditForm( class DeviceBayBulkEditForm( form_from_model(DeviceBay, ['label', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=DeviceBay.objects.all(), @@ -1210,8 +1201,7 @@ class DeviceBayBulkEditForm( class InventoryItemBulkEditForm( form_from_model(InventoryItem, ['label', 'role', 'manufacturer', 'part_id', 'description']), - AddRemoveTagsForm, - CustomFieldModelBulkEditForm + NetBoxModelBulkEditForm ): pk = forms.ModelMultipleChoiceField( queryset=InventoryItem.objects.all(), @@ -1234,7 +1224,7 @@ class InventoryItemBulkEditForm( # Device component roles # -class InventoryItemRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class InventoryItemRoleBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=InventoryItemRole.objects.all(), widget=forms.MultipleHiddenInput diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 1aec329eb..3974c4d54 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -7,8 +7,8 @@ from django.utils.safestring import mark_safe from dcim.choices import * from dcim.constants import * from dcim.models import * -from extras.forms import CustomFieldModelCSVForm from ipam.models import VRF +from netbox.forms import NetBoxModelCSVForm from tenancy.models import Tenant from utilities.forms import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVTypedChoiceField, SlugField from virtualization.models import Cluster @@ -46,7 +46,7 @@ __all__ = ( ) -class RegionCSVForm(CustomFieldModelCSVForm): +class RegionCSVForm(NetBoxModelCSVForm): parent = CSVModelChoiceField( queryset=Region.objects.all(), required=False, @@ -59,7 +59,7 @@ class RegionCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'parent', 'description') -class SiteGroupCSVForm(CustomFieldModelCSVForm): +class SiteGroupCSVForm(NetBoxModelCSVForm): parent = CSVModelChoiceField( queryset=SiteGroup.objects.all(), required=False, @@ -72,7 +72,7 @@ class SiteGroupCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'parent', 'description') -class SiteCSVForm(CustomFieldModelCSVForm): +class SiteCSVForm(NetBoxModelCSVForm): status = CSVChoiceField( choices=SiteStatusChoices, help_text='Operational status' @@ -109,7 +109,7 @@ class SiteCSVForm(CustomFieldModelCSVForm): } -class LocationCSVForm(CustomFieldModelCSVForm): +class LocationCSVForm(NetBoxModelCSVForm): site = CSVModelChoiceField( queryset=Site.objects.all(), to_field_name='name', @@ -136,7 +136,7 @@ class LocationCSVForm(CustomFieldModelCSVForm): fields = ('site', 'parent', 'name', 'slug', 'tenant', 'description') -class RackRoleCSVForm(CustomFieldModelCSVForm): +class RackRoleCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -147,7 +147,7 @@ class RackRoleCSVForm(CustomFieldModelCSVForm): } -class RackCSVForm(CustomFieldModelCSVForm): +class RackCSVForm(NetBoxModelCSVForm): site = CSVModelChoiceField( queryset=Site.objects.all(), to_field_name='name' @@ -205,7 +205,7 @@ class RackCSVForm(CustomFieldModelCSVForm): self.fields['location'].queryset = self.fields['location'].queryset.filter(**params) -class RackReservationCSVForm(CustomFieldModelCSVForm): +class RackReservationCSVForm(NetBoxModelCSVForm): site = CSVModelChoiceField( queryset=Site.objects.all(), to_field_name='name', @@ -255,14 +255,14 @@ class RackReservationCSVForm(CustomFieldModelCSVForm): self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params) -class ManufacturerCSVForm(CustomFieldModelCSVForm): +class ManufacturerCSVForm(NetBoxModelCSVForm): class Meta: model = Manufacturer fields = ('name', 'slug', 'description') -class DeviceRoleCSVForm(CustomFieldModelCSVForm): +class DeviceRoleCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -273,7 +273,7 @@ class DeviceRoleCSVForm(CustomFieldModelCSVForm): } -class PlatformCSVForm(CustomFieldModelCSVForm): +class PlatformCSVForm(NetBoxModelCSVForm): slug = SlugField() manufacturer = CSVModelChoiceField( queryset=Manufacturer.objects.all(), @@ -287,7 +287,7 @@ class PlatformCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args', 'description') -class BaseDeviceCSVForm(CustomFieldModelCSVForm): +class BaseDeviceCSVForm(NetBoxModelCSVForm): device_role = CSVModelChoiceField( queryset=DeviceRole.objects.all(), to_field_name='name', @@ -403,7 +403,7 @@ class DeviceCSVForm(BaseDeviceCSVForm): self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params) -class ModuleCSVForm(CustomFieldModelCSVForm): +class ModuleCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -478,7 +478,7 @@ class ChildDeviceCSVForm(BaseDeviceCSVForm): # Device components # -class ConsolePortCSVForm(CustomFieldModelCSVForm): +class ConsolePortCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -501,7 +501,7 @@ class ConsolePortCSVForm(CustomFieldModelCSVForm): fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description') -class ConsoleServerPortCSVForm(CustomFieldModelCSVForm): +class ConsoleServerPortCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -524,7 +524,7 @@ class ConsoleServerPortCSVForm(CustomFieldModelCSVForm): fields = ('device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description') -class PowerPortCSVForm(CustomFieldModelCSVForm): +class PowerPortCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -542,7 +542,7 @@ class PowerPortCSVForm(CustomFieldModelCSVForm): ) -class PowerOutletCSVForm(CustomFieldModelCSVForm): +class PowerOutletCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -591,7 +591,7 @@ class PowerOutletCSVForm(CustomFieldModelCSVForm): self.fields['power_port'].queryset = PowerPort.objects.none() -class InterfaceCSVForm(CustomFieldModelCSVForm): +class InterfaceCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -655,7 +655,7 @@ class InterfaceCSVForm(CustomFieldModelCSVForm): return self.cleaned_data['enabled'] -class FrontPortCSVForm(CustomFieldModelCSVForm): +class FrontPortCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -703,7 +703,7 @@ class FrontPortCSVForm(CustomFieldModelCSVForm): self.fields['rear_port'].queryset = RearPort.objects.none() -class RearPortCSVForm(CustomFieldModelCSVForm): +class RearPortCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -721,7 +721,7 @@ class RearPortCSVForm(CustomFieldModelCSVForm): } -class ModuleBayCSVForm(CustomFieldModelCSVForm): +class ModuleBayCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -732,7 +732,7 @@ class ModuleBayCSVForm(CustomFieldModelCSVForm): fields = ('device', 'name', 'label', 'position', 'description') -class DeviceBayCSVForm(CustomFieldModelCSVForm): +class DeviceBayCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -778,7 +778,7 @@ class DeviceBayCSVForm(CustomFieldModelCSVForm): self.fields['installed_device'].queryset = Interface.objects.none() -class InventoryItemCSVForm(CustomFieldModelCSVForm): +class InventoryItemCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name' @@ -827,7 +827,7 @@ class InventoryItemCSVForm(CustomFieldModelCSVForm): # Device component roles # -class InventoryItemRoleCSVForm(CustomFieldModelCSVForm): +class InventoryItemRoleCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -842,7 +842,7 @@ class InventoryItemRoleCSVForm(CustomFieldModelCSVForm): # Cables # -class CableCSVForm(CustomFieldModelCSVForm): +class CableCSVForm(NetBoxModelCSVForm): # Termination A side_a_device = CSVModelChoiceField( queryset=Device.objects.all(), @@ -947,7 +947,7 @@ class CableCSVForm(CustomFieldModelCSVForm): # Virtual chassis # -class VirtualChassisCSVForm(CustomFieldModelCSVForm): +class VirtualChassisCSVForm(NetBoxModelCSVForm): master = CSVModelChoiceField( queryset=Device.objects.all(), to_field_name='name', @@ -964,7 +964,7 @@ class VirtualChassisCSVForm(CustomFieldModelCSVForm): # Power # -class PowerPanelCSVForm(CustomFieldModelCSVForm): +class PowerPanelCSVForm(NetBoxModelCSVForm): site = CSVModelChoiceField( queryset=Site.objects.all(), to_field_name='name', @@ -990,7 +990,7 @@ class PowerPanelCSVForm(CustomFieldModelCSVForm): self.fields['location'].queryset = self.fields['location'].queryset.filter(**params) -class PowerFeedCSVForm(CustomFieldModelCSVForm): +class PowerFeedCSVForm(NetBoxModelCSVForm): site = CSVModelChoiceField( queryset=Site.objects.all(), to_field_name='name', diff --git a/netbox/dcim/forms/connections.py b/netbox/dcim/forms/connections.py index 6a7a09023..7ae6a898a 100644 --- a/netbox/dcim/forms/connections.py +++ b/netbox/dcim/forms/connections.py @@ -1,7 +1,7 @@ from circuits.models import Circuit, CircuitTermination, Provider from dcim.models import * -from extras.forms import CustomFieldModelForm from extras.models import Tag +from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms import DynamicModelChoiceField, DynamicModelMultipleChoiceField, StaticSelect @@ -18,7 +18,7 @@ __all__ = ( ) -class ConnectCableToDeviceForm(TenancyForm, CustomFieldModelForm): +class ConnectCableToDeviceForm(TenancyForm, NetBoxModelForm): """ Base form for connecting a Cable to a Device component """ @@ -171,7 +171,7 @@ class ConnectCableToRearPortForm(ConnectCableToDeviceForm): ) -class ConnectCableToCircuitTerminationForm(TenancyForm, CustomFieldModelForm): +class ConnectCableToCircuitTerminationForm(TenancyForm, NetBoxModelForm): termination_b_provider = DynamicModelChoiceField( queryset=Provider.objects.all(), label='Provider', @@ -229,7 +229,7 @@ class ConnectCableToCircuitTerminationForm(TenancyForm, CustomFieldModelForm): return getattr(self.cleaned_data['termination_b_id'], 'pk', None) -class ConnectCableToPowerFeedForm(TenancyForm, CustomFieldModelForm): +class ConnectCableToPowerFeedForm(TenancyForm, NetBoxModelForm): termination_b_region = DynamicModelChoiceField( queryset=Region.objects.all(), label='Region', diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 8868cdf78..e9aa3ec3f 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -5,8 +5,9 @@ from django.utils.translation import gettext as _ from dcim.choices import * from dcim.constants import * from dcim.models import * -from extras.forms import CustomFieldModelFilterForm, LocalConfigContextFilterForm +from extras.forms import LocalConfigContextFilterForm from ipam.models import ASN, VRF +from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import ( APISelectMultiple, add_blank_choice, ColorField, DynamicModelMultipleChoiceField, FilterForm, StaticSelect, @@ -52,7 +53,7 @@ __all__ = ( ) -class DeviceComponentFilterForm(CustomFieldModelFilterForm): +class DeviceComponentFilterForm(NetBoxModelFilterSetForm): name = forms.CharField( required=False ) @@ -103,7 +104,7 @@ class DeviceComponentFilterForm(CustomFieldModelFilterForm): ) -class RegionFilterForm(CustomFieldModelFilterForm): +class RegionFilterForm(NetBoxModelFilterSetForm): model = Region parent_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), @@ -113,7 +114,7 @@ class RegionFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class SiteGroupFilterForm(CustomFieldModelFilterForm): +class SiteGroupFilterForm(NetBoxModelFilterSetForm): model = SiteGroup parent_id = DynamicModelMultipleChoiceField( queryset=SiteGroup.objects.all(), @@ -123,7 +124,7 @@ class SiteGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class SiteFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class SiteFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Site field_groups = [ ['q', 'tag'], @@ -154,7 +155,7 @@ class SiteFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class LocationFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class LocationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Location field_groups = [ ['q', 'tag'], @@ -192,12 +193,12 @@ class LocationFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class RackRoleFilterForm(CustomFieldModelFilterForm): +class RackRoleFilterForm(NetBoxModelFilterSetForm): model = RackRole tag = TagFilterField(model) -class RackFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class RackFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Rack field_groups = [ ['q', 'tag'], @@ -270,7 +271,7 @@ class RackElevationFilterForm(RackFilterForm): ) -class RackReservationFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = RackReservation field_groups = [ ['q', 'tag'], @@ -308,12 +309,12 @@ class RackReservationFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class ManufacturerFilterForm(CustomFieldModelFilterForm): +class ManufacturerFilterForm(NetBoxModelFilterSetForm): model = Manufacturer tag = TagFilterField(model) -class DeviceTypeFilterForm(CustomFieldModelFilterForm): +class DeviceTypeFilterForm(NetBoxModelFilterSetForm): model = DeviceType field_groups = [ ['q', 'tag'], @@ -383,7 +384,7 @@ class DeviceTypeFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class ModuleTypeFilterForm(CustomFieldModelFilterForm): +class ModuleTypeFilterForm(NetBoxModelFilterSetForm): model = ModuleType field_groups = [ ['q', 'tag'], @@ -444,12 +445,12 @@ class ModuleTypeFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class DeviceRoleFilterForm(CustomFieldModelFilterForm): +class DeviceRoleFilterForm(NetBoxModelFilterSetForm): model = DeviceRole tag = TagFilterField(model) -class PlatformFilterForm(CustomFieldModelFilterForm): +class PlatformFilterForm(NetBoxModelFilterSetForm): model = Platform manufacturer_id = DynamicModelMultipleChoiceField( queryset=Manufacturer.objects.all(), @@ -459,7 +460,7 @@ class PlatformFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class DeviceFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, CustomFieldModelFilterForm): +class DeviceFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm): model = Device field_groups = [ ['q', 'tag'], @@ -613,7 +614,7 @@ class DeviceFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, CustomFi tag = TagFilterField(model) -class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, CustomFieldModelFilterForm): +class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm): model = Module field_groups = [ ['q', 'tag'], @@ -644,7 +645,7 @@ class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, CustomFi tag = TagFilterField(model) -class VirtualChassisFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class VirtualChassisFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VirtualChassis field_groups = [ ['q', 'tag'], @@ -673,7 +674,7 @@ class VirtualChassisFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class CableFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class CableFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Cable field_groups = [ ['q', 'tag'], @@ -736,7 +737,7 @@ class CableFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class PowerPanelFilterForm(CustomFieldModelFilterForm): +class PowerPanelFilterForm(NetBoxModelFilterSetForm): model = PowerPanel field_groups = ( ('q', 'tag'), @@ -773,7 +774,7 @@ class PowerPanelFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class PowerFeedFilterForm(CustomFieldModelFilterForm): +class PowerFeedFilterForm(NetBoxModelFilterSetForm): model = PowerFeed field_groups = [ ['q', 'tag'], @@ -1103,7 +1104,7 @@ class InventoryItemFilterForm(DeviceComponentFilterForm): # Device component roles # -class InventoryItemRoleFilterForm(CustomFieldModelFilterForm): +class InventoryItemRoleFilterForm(NetBoxModelFilterSetForm): model = InventoryItemRole tag = TagFilterField(model) diff --git a/netbox/dcim/forms/models.py b/netbox/dcim/forms/models.py index 378a567fc..80e785940 100644 --- a/netbox/dcim/forms/models.py +++ b/netbox/dcim/forms/models.py @@ -7,9 +7,9 @@ from timezone_field import TimeZoneFormField from dcim.choices import * from dcim.constants import * from dcim.models import * -from extras.forms import CustomFieldModelForm from extras.models import Tag from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VRF +from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms import ( APISelect, add_blank_choice, BootstrapMixin, ClearableFileInput, CommentField, ContentTypeChoiceField, @@ -72,7 +72,7 @@ Tagged (All): Implies all VLANs are available (w/optional untagged VLAN) """ -class RegionForm(CustomFieldModelForm): +class RegionForm(NetBoxModelForm): parent = DynamicModelChoiceField( queryset=Region.objects.all(), required=False @@ -90,7 +90,7 @@ class RegionForm(CustomFieldModelForm): ) -class SiteGroupForm(CustomFieldModelForm): +class SiteGroupForm(NetBoxModelForm): parent = DynamicModelChoiceField( queryset=SiteGroup.objects.all(), required=False @@ -108,7 +108,7 @@ class SiteGroupForm(CustomFieldModelForm): ) -class SiteForm(TenancyForm, CustomFieldModelForm): +class SiteForm(TenancyForm, NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False @@ -173,7 +173,7 @@ class SiteForm(TenancyForm, CustomFieldModelForm): } -class LocationForm(TenancyForm, CustomFieldModelForm): +class LocationForm(TenancyForm, NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -221,7 +221,7 @@ class LocationForm(TenancyForm, CustomFieldModelForm): ) -class RackRoleForm(CustomFieldModelForm): +class RackRoleForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -235,7 +235,7 @@ class RackRoleForm(CustomFieldModelForm): ] -class RackForm(TenancyForm, CustomFieldModelForm): +class RackForm(TenancyForm, NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -295,7 +295,7 @@ class RackForm(TenancyForm, CustomFieldModelForm): } -class RackReservationForm(TenancyForm, CustomFieldModelForm): +class RackReservationForm(TenancyForm, NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -359,7 +359,7 @@ class RackReservationForm(TenancyForm, CustomFieldModelForm): ) -class ManufacturerForm(CustomFieldModelForm): +class ManufacturerForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -373,7 +373,7 @@ class ManufacturerForm(CustomFieldModelForm): ] -class DeviceTypeForm(CustomFieldModelForm): +class DeviceTypeForm(NetBoxModelForm): manufacturer = DynamicModelChoiceField( queryset=Manufacturer.objects.all() ) @@ -412,7 +412,7 @@ class DeviceTypeForm(CustomFieldModelForm): } -class ModuleTypeForm(CustomFieldModelForm): +class ModuleTypeForm(NetBoxModelForm): manufacturer = DynamicModelChoiceField( queryset=Manufacturer.objects.all() ) @@ -429,7 +429,7 @@ class ModuleTypeForm(CustomFieldModelForm): ] -class DeviceRoleForm(CustomFieldModelForm): +class DeviceRoleForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -443,7 +443,7 @@ class DeviceRoleForm(CustomFieldModelForm): ] -class PlatformForm(CustomFieldModelForm): +class PlatformForm(NetBoxModelForm): manufacturer = DynamicModelChoiceField( queryset=Manufacturer.objects.all(), required=False @@ -466,7 +466,7 @@ class PlatformForm(CustomFieldModelForm): } -class DeviceForm(TenancyForm, CustomFieldModelForm): +class DeviceForm(TenancyForm, NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -648,7 +648,7 @@ class DeviceForm(TenancyForm, CustomFieldModelForm): self.fields['position'].widget.choices = [(position, f'U{position}')] -class ModuleForm(CustomFieldModelForm): +class ModuleForm(NetBoxModelForm): device = DynamicModelChoiceField( queryset=Device.objects.all(), required=False, @@ -688,7 +688,7 @@ class ModuleForm(CustomFieldModelForm): ] -class CableForm(TenancyForm, CustomFieldModelForm): +class CableForm(TenancyForm, NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -711,7 +711,7 @@ class CableForm(TenancyForm, CustomFieldModelForm): } -class PowerPanelForm(CustomFieldModelForm): +class PowerPanelForm(NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -755,7 +755,7 @@ class PowerPanelForm(CustomFieldModelForm): ) -class PowerFeedForm(CustomFieldModelForm): +class PowerFeedForm(NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -823,7 +823,7 @@ class PowerFeedForm(CustomFieldModelForm): # Virtual chassis # -class VirtualChassisForm(CustomFieldModelForm): +class VirtualChassisForm(NetBoxModelForm): master = forms.ModelChoiceField( queryset=Device.objects.all(), required=False, @@ -1120,7 +1120,7 @@ class InventoryItemTemplateForm(BootstrapMixin, forms.ModelForm): # Device components # -class ConsolePortForm(CustomFieldModelForm): +class ConsolePortForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -1138,7 +1138,7 @@ class ConsolePortForm(CustomFieldModelForm): } -class ConsoleServerPortForm(CustomFieldModelForm): +class ConsoleServerPortForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -1156,7 +1156,7 @@ class ConsoleServerPortForm(CustomFieldModelForm): } -class PowerPortForm(CustomFieldModelForm): +class PowerPortForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -1174,7 +1174,7 @@ class PowerPortForm(CustomFieldModelForm): } -class PowerOutletForm(CustomFieldModelForm): +class PowerOutletForm(NetBoxModelForm): power_port = DynamicModelChoiceField( queryset=PowerPort.objects.all(), required=False, @@ -1199,7 +1199,7 @@ class PowerOutletForm(CustomFieldModelForm): } -class InterfaceForm(InterfaceCommonForm, CustomFieldModelForm): +class InterfaceForm(InterfaceCommonForm, NetBoxModelForm): parent = DynamicModelChoiceField( queryset=Interface.objects.all(), required=False, @@ -1308,7 +1308,7 @@ class InterfaceForm(InterfaceCommonForm, CustomFieldModelForm): } -class FrontPortForm(CustomFieldModelForm): +class FrontPortForm(NetBoxModelForm): rear_port = DynamicModelChoiceField( queryset=RearPort.objects.all(), query_params={ @@ -1332,7 +1332,7 @@ class FrontPortForm(CustomFieldModelForm): } -class RearPortForm(CustomFieldModelForm): +class RearPortForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -1349,7 +1349,7 @@ class RearPortForm(CustomFieldModelForm): } -class ModuleBayForm(CustomFieldModelForm): +class ModuleBayForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -1365,7 +1365,7 @@ class ModuleBayForm(CustomFieldModelForm): } -class DeviceBayForm(CustomFieldModelForm): +class DeviceBayForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -1401,7 +1401,7 @@ class PopulateDeviceBayForm(BootstrapMixin, forms.Form): ).exclude(pk=device_bay.device.pk) -class InventoryItemForm(CustomFieldModelForm): +class InventoryItemForm(NetBoxModelForm): parent = DynamicModelChoiceField( queryset=InventoryItem.objects.all(), required=False, @@ -1451,7 +1451,7 @@ class InventoryItemForm(CustomFieldModelForm): # Device component roles # -class InventoryItemRoleForm(CustomFieldModelForm): +class InventoryItemRoleForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), diff --git a/netbox/dcim/forms/object_create.py b/netbox/dcim/forms/object_create.py index 1fea886ea..73bb621fc 100644 --- a/netbox/dcim/forms/object_create.py +++ b/netbox/dcim/forms/object_create.py @@ -1,8 +1,8 @@ from django import forms from dcim.models import * -from extras.forms import CustomFieldModelForm from extras.models import Tag +from netbox.forms import NetBoxModelForm from utilities.forms import ( BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, ) @@ -149,7 +149,7 @@ class FrontPortCreateForm(DeviceComponentCreateForm): } -class VirtualChassisCreateForm(CustomFieldModelForm): +class VirtualChassisCreateForm(NetBoxModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, diff --git a/netbox/extras/forms/customfields.py b/netbox/extras/forms/customfields.py index 8912d0365..c3a44f47b 100644 --- a/netbox/extras/forms/customfields.py +++ b/netbox/extras/forms/customfields.py @@ -1,16 +1,8 @@ -from django import forms from django.contrib.contenttypes.models import ContentType -from django.db.models import Q -from extras.choices import * from extras.models import * -from utilities.forms import BootstrapMixin, BulkEditBaseForm, CSVModelForm __all__ = ( - 'CustomFieldModelCSVForm', - 'CustomFieldModelBulkEditForm', - 'CustomFieldModelFilterForm', - 'CustomFieldModelForm', 'CustomFieldsMixin', ) @@ -50,76 +42,3 @@ class CustomFieldsMixin: # Annotate the field in the list of CustomField form fields self.custom_fields[field_name] = customfield - - -class CustomFieldModelForm(BootstrapMixin, CustomFieldsMixin, forms.ModelForm): - """ - Extend ModelForm to include custom field support. - """ - def _get_content_type(self): - return ContentType.objects.get_for_model(self._meta.model) - - def _get_form_field(self, customfield): - if self.instance.pk: - form_field = customfield.to_form_field(set_initial=False) - form_field.initial = self.instance.custom_field_data.get(customfield.name, None) - return form_field - - return customfield.to_form_field() - - def clean(self): - - # Save custom field data on instance - for cf_name, customfield in self.custom_fields.items(): - key = cf_name[3:] # Strip "cf_" from field name - value = self.cleaned_data.get(cf_name) - - # Convert "empty" values to null - if value in self.fields[cf_name].empty_values: - self.instance.custom_field_data[key] = None - else: - self.instance.custom_field_data[key] = customfield.serialize(value) - - return super().clean() - - -class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelForm): - - def _get_form_field(self, customfield): - return customfield.to_form_field(for_csv_import=True) - - -class CustomFieldModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, BulkEditBaseForm): - - def _get_form_field(self, customfield): - return customfield.to_form_field(set_initial=False, enforce_required=False) - - def _append_customfield_fields(self): - """ - Append form fields for all CustomFields assigned to this object type. - """ - for customfield in self._get_custom_fields(self._get_content_type()): - # Annotate non-required custom fields as nullable - if not customfield.required: - self.nullable_fields.append(customfield.name) - - self.fields[customfield.name] = self._get_form_field(customfield) - - # Annotate the field in the list of CustomField form fields - self.custom_fields[customfield.name] = customfield - - -class CustomFieldModelFilterForm(BootstrapMixin, CustomFieldsMixin, forms.Form): - q = forms.CharField( - required=False, - label='Search' - ) - - def _get_custom_fields(self, content_type): - return CustomField.objects.filter(content_types=content_type).exclude( - Q(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED) | - Q(type=CustomFieldTypeChoices.TYPE_JSON) - ) - - def _get_form_field(self, customfield): - return customfield.to_form_field(set_initial=False, enforce_required=False) diff --git a/netbox/extras/forms/models.py b/netbox/extras/forms/models.py index 9aac8454b..5c29a8381 100644 --- a/netbox/extras/forms/models.py +++ b/netbox/extras/forms/models.py @@ -13,7 +13,6 @@ from utilities.forms import ( from virtualization.models import Cluster, ClusterGroup, ClusterType __all__ = ( - 'AddRemoveTagsForm', 'ConfigContextForm', 'CustomFieldForm', 'CustomLinkForm', @@ -134,22 +133,6 @@ class TagForm(BootstrapMixin, forms.ModelForm): ) -class AddRemoveTagsForm(forms.Form): - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Add add/remove tags fields - self.fields['add_tags'] = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) - self.fields['remove_tags'] = DynamicModelMultipleChoiceField( - queryset=Tag.objects.all(), - required=False - ) - - class ConfigContextForm(BootstrapMixin, forms.ModelForm): regions = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py index 308a467d1..3da03dd41 100644 --- a/netbox/ipam/forms/bulk_edit.py +++ b/netbox/ipam/forms/bulk_edit.py @@ -1,11 +1,11 @@ from django import forms from dcim.models import Region, Site, SiteGroup -from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm from ipam.choices import * from ipam.constants import * from ipam.models import * from ipam.models import ASN +from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import ( add_blank_choice, BulkEditNullBooleanSelect, DatePicker, DynamicModelChoiceField, NumericArrayField, StaticSelect, @@ -30,7 +30,7 @@ __all__ = ( ) -class VRFBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class VRFBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VRF.objects.all(), widget=forms.MultipleHiddenInput() @@ -55,7 +55,7 @@ class VRFBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class RouteTargetBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RouteTargetBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=RouteTarget.objects.all(), widget=forms.MultipleHiddenInput() @@ -75,7 +75,7 @@ class RouteTargetBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class RIRBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RIRBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=RIR.objects.all(), widget=forms.MultipleHiddenInput @@ -93,7 +93,7 @@ class RIRBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['is_private', 'description'] -class ASNBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ASNBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ASN.objects.all(), widget=forms.MultipleHiddenInput() @@ -125,7 +125,7 @@ class ASNBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): } -class AggregateBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class AggregateBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Aggregate.objects.all(), widget=forms.MultipleHiddenInput() @@ -156,7 +156,7 @@ class AggregateBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): } -class RoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class RoleBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Role.objects.all(), widget=forms.MultipleHiddenInput @@ -173,7 +173,7 @@ class RoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['description'] -class PrefixBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class PrefixBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Prefix.objects.all(), widget=forms.MultipleHiddenInput() @@ -238,7 +238,7 @@ class PrefixBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class IPRangeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class IPRangeBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=IPRange.objects.all(), widget=forms.MultipleHiddenInput() @@ -272,7 +272,7 @@ class IPRangeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class IPAddressBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class IPAddressBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=IPAddress.objects.all(), widget=forms.MultipleHiddenInput() @@ -317,7 +317,7 @@ class IPAddressBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class FHRPGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=FHRPGroup.objects.all(), widget=forms.MultipleHiddenInput() @@ -352,7 +352,7 @@ class FHRPGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['auth_type', 'auth_key', 'description'] -class VLANGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class VLANGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VLANGroup.objects.all(), widget=forms.MultipleHiddenInput @@ -382,7 +382,7 @@ class VLANGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['site', 'description'] -class VLANBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class VLANBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VLAN.objects.all(), widget=forms.MultipleHiddenInput() @@ -434,7 +434,7 @@ class VLANBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class ServiceTemplateBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ServiceTemplateBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ServiceTemplate.objects.all(), widget=forms.MultipleHiddenInput() diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index 1ae977fe5..365f82858 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -2,10 +2,10 @@ from django import forms from django.contrib.contenttypes.models import ContentType from dcim.models import Device, Interface, Site -from extras.forms import CustomFieldModelCSVForm from ipam.choices import * from ipam.constants import * from ipam.models import * +from netbox.forms import NetBoxModelCSVForm from tenancy.models import Tenant from utilities.forms import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, SlugField from virtualization.models import VirtualMachine, VMInterface @@ -28,7 +28,7 @@ __all__ = ( ) -class VRFCSVForm(CustomFieldModelCSVForm): +class VRFCSVForm(NetBoxModelCSVForm): tenant = CSVModelChoiceField( queryset=Tenant.objects.all(), required=False, @@ -41,7 +41,7 @@ class VRFCSVForm(CustomFieldModelCSVForm): fields = ('name', 'rd', 'tenant', 'enforce_unique', 'description') -class RouteTargetCSVForm(CustomFieldModelCSVForm): +class RouteTargetCSVForm(NetBoxModelCSVForm): tenant = CSVModelChoiceField( queryset=Tenant.objects.all(), required=False, @@ -54,7 +54,7 @@ class RouteTargetCSVForm(CustomFieldModelCSVForm): fields = ('name', 'description', 'tenant') -class RIRCSVForm(CustomFieldModelCSVForm): +class RIRCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -65,7 +65,7 @@ class RIRCSVForm(CustomFieldModelCSVForm): } -class AggregateCSVForm(CustomFieldModelCSVForm): +class AggregateCSVForm(NetBoxModelCSVForm): rir = CSVModelChoiceField( queryset=RIR.objects.all(), to_field_name='name', @@ -83,7 +83,7 @@ class AggregateCSVForm(CustomFieldModelCSVForm): fields = ('prefix', 'rir', 'tenant', 'date_added', 'description') -class ASNCSVForm(CustomFieldModelCSVForm): +class ASNCSVForm(NetBoxModelCSVForm): rir = CSVModelChoiceField( queryset=RIR.objects.all(), to_field_name='name', @@ -102,7 +102,7 @@ class ASNCSVForm(CustomFieldModelCSVForm): help_texts = {} -class RoleCSVForm(CustomFieldModelCSVForm): +class RoleCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -110,7 +110,7 @@ class RoleCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'weight', 'description') -class PrefixCSVForm(CustomFieldModelCSVForm): +class PrefixCSVForm(NetBoxModelCSVForm): vrf = CSVModelChoiceField( queryset=VRF.objects.all(), to_field_name='name', @@ -174,7 +174,7 @@ class PrefixCSVForm(CustomFieldModelCSVForm): self.fields['vlan'].queryset = self.fields['vlan'].queryset.filter(**params) -class IPRangeCSVForm(CustomFieldModelCSVForm): +class IPRangeCSVForm(NetBoxModelCSVForm): vrf = CSVModelChoiceField( queryset=VRF.objects.all(), to_field_name='name', @@ -205,7 +205,7 @@ class IPRangeCSVForm(CustomFieldModelCSVForm): ) -class IPAddressCSVForm(CustomFieldModelCSVForm): +class IPAddressCSVForm(NetBoxModelCSVForm): vrf = CSVModelChoiceField( queryset=VRF.objects.all(), to_field_name='name', @@ -312,7 +312,7 @@ class IPAddressCSVForm(CustomFieldModelCSVForm): return ipaddress -class FHRPGroupCSVForm(CustomFieldModelCSVForm): +class FHRPGroupCSVForm(NetBoxModelCSVForm): protocol = CSVChoiceField( choices=FHRPGroupProtocolChoices ) @@ -326,7 +326,7 @@ class FHRPGroupCSVForm(CustomFieldModelCSVForm): fields = ('protocol', 'group_id', 'auth_type', 'auth_key', 'description') -class VLANGroupCSVForm(CustomFieldModelCSVForm): +class VLANGroupCSVForm(NetBoxModelCSVForm): slug = SlugField() scope_type = CSVContentTypeField( queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), @@ -354,7 +354,7 @@ class VLANGroupCSVForm(CustomFieldModelCSVForm): } -class VLANCSVForm(CustomFieldModelCSVForm): +class VLANCSVForm(NetBoxModelCSVForm): site = CSVModelChoiceField( queryset=Site.objects.all(), required=False, @@ -393,7 +393,7 @@ class VLANCSVForm(CustomFieldModelCSVForm): } -class ServiceTemplateCSVForm(CustomFieldModelCSVForm): +class ServiceTemplateCSVForm(NetBoxModelCSVForm): protocol = CSVChoiceField( choices=ServiceProtocolChoices, help_text='IP protocol' @@ -404,7 +404,7 @@ class ServiceTemplateCSVForm(CustomFieldModelCSVForm): fields = ('name', 'protocol', 'ports', 'description') -class ServiceCSVForm(CustomFieldModelCSVForm): +class ServiceCSVForm(NetBoxModelCSVForm): device = CSVModelChoiceField( queryset=Device.objects.all(), required=False, diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index 9bfb1df10..4301a1810 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -2,11 +2,11 @@ from django import forms from django.utils.translation import gettext as _ from dcim.models import Location, Rack, Region, Site, SiteGroup -from extras.forms import CustomFieldModelFilterForm from ipam.choices import * from ipam.constants import * from ipam.models import * from ipam.models import ASN +from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import ( add_blank_choice, DynamicModelChoiceField, DynamicModelMultipleChoiceField, StaticSelect, StaticSelectMultiple, @@ -39,7 +39,7 @@ IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([ ]) -class VRFFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class VRFFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VRF field_groups = [ ['q', 'tag'], @@ -59,7 +59,7 @@ class VRFFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class RouteTargetFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class RouteTargetFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = RouteTarget field_groups = [ ['q', 'tag'], @@ -79,7 +79,7 @@ class RouteTargetFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class RIRFilterForm(CustomFieldModelFilterForm): +class RIRFilterForm(NetBoxModelFilterSetForm): model = RIR is_private = forms.NullBooleanField( required=False, @@ -91,7 +91,7 @@ class RIRFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class AggregateFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class AggregateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Aggregate field_groups = [ ['q', 'tag'], @@ -112,7 +112,7 @@ class AggregateFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class ASNFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = ASN field_groups = [ ['q'], @@ -132,12 +132,12 @@ class ASNFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): ) -class RoleFilterForm(CustomFieldModelFilterForm): +class RoleFilterForm(NetBoxModelFilterSetForm): model = Role tag = TagFilterField(model) -class PrefixFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Prefix field_groups = [ ['q', 'tag'], @@ -228,7 +228,7 @@ class PrefixFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class IPRangeFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = IPRange field_groups = [ ['q', 'tag'], @@ -261,7 +261,7 @@ class IPRangeFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class IPAddressFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = IPAddress field_groups = [ ['q', 'tag'], @@ -321,7 +321,7 @@ class IPAddressFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class FHRPGroupFilterForm(CustomFieldModelFilterForm): +class FHRPGroupFilterForm(NetBoxModelFilterSetForm): model = FHRPGroup field_groups = ( ('q', 'tag'), @@ -351,7 +351,7 @@ class FHRPGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class VLANGroupFilterForm(CustomFieldModelFilterForm): +class VLANGroupFilterForm(NetBoxModelFilterSetForm): field_groups = [ ['q', 'tag'], ['region', 'sitegroup', 'site', 'location', 'rack'], @@ -394,7 +394,7 @@ class VLANGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class VLANFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VLAN field_groups = [ ['q', 'tag'], @@ -448,7 +448,7 @@ class VLANFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class ServiceTemplateFilterForm(CustomFieldModelFilterForm): +class ServiceTemplateFilterForm(NetBoxModelFilterSetForm): model = ServiceTemplate field_groups = ( ('q', 'tag'), diff --git a/netbox/ipam/forms/models.py b/netbox/ipam/forms/models.py index 34c67773f..e86fe1dab 100644 --- a/netbox/ipam/forms/models.py +++ b/netbox/ipam/forms/models.py @@ -2,13 +2,13 @@ from django import forms from django.contrib.contenttypes.models import ContentType from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup -from extras.forms import CustomFieldModelForm from extras.models import Tag from ipam.choices import * from ipam.constants import * from ipam.formfields import IPNetworkFormField from ipam.models import * from ipam.models import ASN +from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.exceptions import PermissionsViolation from utilities.forms import ( @@ -39,7 +39,7 @@ __all__ = ( ) -class VRFForm(TenancyForm, CustomFieldModelForm): +class VRFForm(TenancyForm, NetBoxModelForm): import_targets = DynamicModelMultipleChoiceField( queryset=RouteTarget.objects.all(), required=False @@ -72,7 +72,7 @@ class VRFForm(TenancyForm, CustomFieldModelForm): } -class RouteTargetForm(TenancyForm, CustomFieldModelForm): +class RouteTargetForm(TenancyForm, NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -89,7 +89,7 @@ class RouteTargetForm(TenancyForm, CustomFieldModelForm): ) -class RIRForm(CustomFieldModelForm): +class RIRForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -103,7 +103,7 @@ class RIRForm(CustomFieldModelForm): ] -class AggregateForm(TenancyForm, CustomFieldModelForm): +class AggregateForm(TenancyForm, NetBoxModelForm): rir = DynamicModelChoiceField( queryset=RIR.objects.all(), label='RIR' @@ -131,7 +131,7 @@ class AggregateForm(TenancyForm, CustomFieldModelForm): } -class ASNForm(TenancyForm, CustomFieldModelForm): +class ASNForm(TenancyForm, NetBoxModelForm): rir = DynamicModelChoiceField( queryset=RIR.objects.all(), label='RIR', @@ -175,7 +175,7 @@ class ASNForm(TenancyForm, CustomFieldModelForm): return instance -class RoleForm(CustomFieldModelForm): +class RoleForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -189,7 +189,7 @@ class RoleForm(CustomFieldModelForm): ] -class PrefixForm(TenancyForm, CustomFieldModelForm): +class PrefixForm(TenancyForm, NetBoxModelForm): vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, @@ -264,7 +264,7 @@ class PrefixForm(TenancyForm, CustomFieldModelForm): } -class IPRangeForm(TenancyForm, CustomFieldModelForm): +class IPRangeForm(TenancyForm, NetBoxModelForm): vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, @@ -293,7 +293,7 @@ class IPRangeForm(TenancyForm, CustomFieldModelForm): } -class IPAddressForm(TenancyForm, CustomFieldModelForm): +class IPAddressForm(TenancyForm, NetBoxModelForm): device = DynamicModelChoiceField( queryset=Device.objects.all(), required=False, @@ -506,7 +506,7 @@ class IPAddressForm(TenancyForm, CustomFieldModelForm): return ipaddress -class IPAddressBulkAddForm(TenancyForm, CustomFieldModelForm): +class IPAddressBulkAddForm(TenancyForm, NetBoxModelForm): vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, @@ -540,7 +540,7 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form): ) -class FHRPGroupForm(CustomFieldModelForm): +class FHRPGroupForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -629,7 +629,7 @@ class FHRPGroupAssignmentForm(BootstrapMixin, forms.ModelForm): self.fields['group'].widget.add_query_param('related_ip', ipaddress.pk) -class VLANGroupForm(CustomFieldModelForm): +class VLANGroupForm(NetBoxModelForm): scope_type = ContentTypeChoiceField( queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), required=False @@ -736,7 +736,7 @@ class VLANGroupForm(CustomFieldModelForm): self.instance.scope_id = None -class VLANForm(TenancyForm, CustomFieldModelForm): +class VLANForm(TenancyForm, NetBoxModelForm): # VLANGroup assignment fields scope_type = forms.ChoiceField( choices=( @@ -817,7 +817,7 @@ class VLANForm(TenancyForm, CustomFieldModelForm): } -class ServiceTemplateForm(CustomFieldModelForm): +class ServiceTemplateForm(NetBoxModelForm): ports = NumericArrayField( base_field=forms.IntegerField( min_value=SERVICE_PORT_MIN, @@ -838,7 +838,7 @@ class ServiceTemplateForm(CustomFieldModelForm): } -class ServiceForm(CustomFieldModelForm): +class ServiceForm(NetBoxModelForm): device = DynamicModelChoiceField( queryset=Device.objects.all(), required=False diff --git a/netbox/netbox/forms.py b/netbox/netbox/forms/__init__.py similarity index 98% rename from netbox/netbox/forms.py rename to netbox/netbox/forms/__init__.py index b5d68c1fc..9984a4461 100644 --- a/netbox/netbox/forms.py +++ b/netbox/netbox/forms/__init__.py @@ -1,6 +1,7 @@ from django import forms from utilities.forms import BootstrapMixin +from .base import * OBJ_TYPE_CHOICES = ( ('', 'All Objects'), diff --git a/netbox/netbox/forms/base.py b/netbox/netbox/forms/base.py new file mode 100644 index 000000000..601b0062a --- /dev/null +++ b/netbox/netbox/forms/base.py @@ -0,0 +1,108 @@ +from django import forms +from django.contrib.contenttypes.models import ContentType +from django.db.models import Q + +from extras.choices import CustomFieldFilterLogicChoices, CustomFieldTypeChoices +from extras.forms.customfields import CustomFieldsMixin +from extras.models import CustomField, Tag +from utilities.forms import BootstrapMixin, BulkEditBaseForm, CSVModelForm +from utilities.forms.fields import DynamicModelMultipleChoiceField + +__all__ = ( + 'NetBoxModelForm', + 'NetBoxModelCSVForm', + 'NetBoxModelBulkEditForm', + 'NetBoxModelFilterSetForm', +) + + +class NetBoxModelForm(BootstrapMixin, CustomFieldsMixin, forms.ModelForm): + """ + Base form for creating & editing NetBox models. Adds support for custom fields. + """ + def _get_content_type(self): + return ContentType.objects.get_for_model(self._meta.model) + + def _get_form_field(self, customfield): + if self.instance.pk: + form_field = customfield.to_form_field(set_initial=False) + form_field.initial = self.instance.custom_field_data.get(customfield.name, None) + return form_field + + return customfield.to_form_field() + + def clean(self): + + # Save custom field data on instance + for cf_name, customfield in self.custom_fields.items(): + key = cf_name[3:] # Strip "cf_" from field name + value = self.cleaned_data.get(cf_name) + + # Convert "empty" values to null + if value in self.fields[cf_name].empty_values: + self.instance.custom_field_data[key] = None + else: + self.instance.custom_field_data[key] = customfield.serialize(value) + + return super().clean() + + +class NetBoxModelCSVForm(CSVModelForm, NetBoxModelForm): + """ + Base form for creating a NetBox objects from CSV data. Used for bulk importing. + """ + def _get_form_field(self, customfield): + return customfield.to_form_field(for_csv_import=True) + + +class NetBoxModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, BulkEditBaseForm): + """ + Base form for modifying multiple NetBox objects (of the same type) in bulk via the UI. Adds support for custom + fields and adding/removing tags. + """ + add_tags = DynamicModelMultipleChoiceField( + queryset=Tag.objects.all(), + required=False + ) + remove_tags = DynamicModelMultipleChoiceField( + queryset=Tag.objects.all(), + required=False + ) + + def _get_form_field(self, customfield): + return customfield.to_form_field(set_initial=False, enforce_required=False) + + def _append_customfield_fields(self): + """ + Append form fields for all CustomFields assigned to this object type. + """ + for customfield in self._get_custom_fields(self._get_content_type()): + # Annotate non-required custom fields as nullable + if not customfield.required: + self.nullable_fields.append(customfield.name) + + self.fields[customfield.name] = self._get_form_field(customfield) + + # Annotate the field in the list of CustomField form fields + self.custom_fields[customfield.name] = customfield + + +class NetBoxModelFilterSetForm(BootstrapMixin, CustomFieldsMixin, forms.Form): + """ + Base form for FilerSet forms. These are used to filter object lists in the NetBox UI. + + The corresponding FilterSet *must* provide a `q` filter. + """ + q = forms.CharField( + required=False, + label='Search' + ) + + def _get_custom_fields(self, content_type): + return CustomField.objects.filter(content_types=content_type).exclude( + Q(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED) | + Q(type=CustomFieldTypeChoices.TYPE_JSON) + ) + + def _get_form_field(self, customfield): + return customfield.to_form_field(set_initial=False, enforce_required=False) diff --git a/netbox/tenancy/forms/bulk_edit.py b/netbox/tenancy/forms/bulk_edit.py index 9dc1b8ec5..9b14a167b 100644 --- a/netbox/tenancy/forms/bulk_edit.py +++ b/netbox/tenancy/forms/bulk_edit.py @@ -1,6 +1,6 @@ from django import forms -from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm +from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import * from utilities.forms import DynamicModelChoiceField @@ -17,7 +17,7 @@ __all__ = ( # Tenants # -class TenantGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class TenantGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=TenantGroup.objects.all(), widget=forms.MultipleHiddenInput @@ -35,7 +35,7 @@ class TenantGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['parent', 'description'] -class TenantBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class TenantBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Tenant.objects.all(), widget=forms.MultipleHiddenInput() @@ -55,7 +55,7 @@ class TenantBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): # Contacts # -class ContactGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ContactGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ContactGroup.objects.all(), widget=forms.MultipleHiddenInput @@ -73,7 +73,7 @@ class ContactGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['parent', 'description'] -class ContactRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ContactRoleBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ContactRole.objects.all(), widget=forms.MultipleHiddenInput @@ -87,7 +87,7 @@ class ContactRoleBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['description'] -class ContactBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ContactBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Contact.objects.all(), widget=forms.MultipleHiddenInput() diff --git a/netbox/tenancy/forms/bulk_import.py b/netbox/tenancy/forms/bulk_import.py index 51b863cac..409590c28 100644 --- a/netbox/tenancy/forms/bulk_import.py +++ b/netbox/tenancy/forms/bulk_import.py @@ -1,4 +1,4 @@ -from extras.forms import CustomFieldModelCSVForm +from netbox.forms import NetBoxModelCSVForm from tenancy.models import * from utilities.forms import CSVModelChoiceField, SlugField @@ -15,7 +15,7 @@ __all__ = ( # Tenants # -class TenantGroupCSVForm(CustomFieldModelCSVForm): +class TenantGroupCSVForm(NetBoxModelCSVForm): parent = CSVModelChoiceField( queryset=TenantGroup.objects.all(), required=False, @@ -29,7 +29,7 @@ class TenantGroupCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'parent', 'description') -class TenantCSVForm(CustomFieldModelCSVForm): +class TenantCSVForm(NetBoxModelCSVForm): slug = SlugField() group = CSVModelChoiceField( queryset=TenantGroup.objects.all(), @@ -47,7 +47,7 @@ class TenantCSVForm(CustomFieldModelCSVForm): # Contacts # -class ContactGroupCSVForm(CustomFieldModelCSVForm): +class ContactGroupCSVForm(NetBoxModelCSVForm): parent = CSVModelChoiceField( queryset=ContactGroup.objects.all(), required=False, @@ -61,7 +61,7 @@ class ContactGroupCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'parent', 'description') -class ContactRoleCSVForm(CustomFieldModelCSVForm): +class ContactRoleCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -69,7 +69,7 @@ class ContactRoleCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'description') -class ContactCSVForm(CustomFieldModelCSVForm): +class ContactCSVForm(NetBoxModelCSVForm): group = CSVModelChoiceField( queryset=ContactGroup.objects.all(), required=False, diff --git a/netbox/tenancy/forms/filtersets.py b/netbox/tenancy/forms/filtersets.py index 7849e2171..8fb4b50ff 100644 --- a/netbox/tenancy/forms/filtersets.py +++ b/netbox/tenancy/forms/filtersets.py @@ -1,6 +1,6 @@ from django.utils.translation import gettext as _ -from extras.forms import CustomFieldModelFilterForm +from netbox.forms import NetBoxModelFilterSetForm from tenancy.models import * from utilities.forms import DynamicModelMultipleChoiceField, TagFilterField @@ -17,7 +17,7 @@ __all__ = ( # Tenants # -class TenantGroupFilterForm(CustomFieldModelFilterForm): +class TenantGroupFilterForm(NetBoxModelFilterSetForm): model = TenantGroup parent_id = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), @@ -27,7 +27,7 @@ class TenantGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class TenantFilterForm(CustomFieldModelFilterForm): +class TenantFilterForm(NetBoxModelFilterSetForm): model = Tenant field_groups = ( ('q', 'tag'), @@ -46,7 +46,7 @@ class TenantFilterForm(CustomFieldModelFilterForm): # Contacts # -class ContactGroupFilterForm(CustomFieldModelFilterForm): +class ContactGroupFilterForm(NetBoxModelFilterSetForm): model = ContactGroup parent_id = DynamicModelMultipleChoiceField( queryset=ContactGroup.objects.all(), @@ -56,12 +56,12 @@ class ContactGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class ContactRoleFilterForm(CustomFieldModelFilterForm): +class ContactRoleFilterForm(NetBoxModelFilterSetForm): model = ContactRole tag = TagFilterField(model) -class ContactFilterForm(CustomFieldModelFilterForm): +class ContactFilterForm(NetBoxModelFilterSetForm): model = Contact field_groups = ( ('q', 'tag'), diff --git a/netbox/tenancy/forms/models.py b/netbox/tenancy/forms/models.py index 398a44c9b..313b55417 100644 --- a/netbox/tenancy/forms/models.py +++ b/netbox/tenancy/forms/models.py @@ -1,7 +1,7 @@ from django import forms -from extras.forms import CustomFieldModelForm from extras.models import Tag +from netbox.forms import NetBoxModelForm from tenancy.models import * from utilities.forms import ( BootstrapMixin, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, SmallTextarea, @@ -22,7 +22,7 @@ __all__ = ( # Tenants # -class TenantGroupForm(CustomFieldModelForm): +class TenantGroupForm(NetBoxModelForm): parent = DynamicModelChoiceField( queryset=TenantGroup.objects.all(), required=False @@ -40,7 +40,7 @@ class TenantGroupForm(CustomFieldModelForm): ] -class TenantForm(CustomFieldModelForm): +class TenantForm(NetBoxModelForm): slug = SlugField() group = DynamicModelChoiceField( queryset=TenantGroup.objects.all(), @@ -66,7 +66,7 @@ class TenantForm(CustomFieldModelForm): # Contacts # -class ContactGroupForm(CustomFieldModelForm): +class ContactGroupForm(NetBoxModelForm): parent = DynamicModelChoiceField( queryset=ContactGroup.objects.all(), required=False @@ -82,7 +82,7 @@ class ContactGroupForm(CustomFieldModelForm): fields = ('parent', 'name', 'slug', 'description', 'tags') -class ContactRoleForm(CustomFieldModelForm): +class ContactRoleForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -94,7 +94,7 @@ class ContactRoleForm(CustomFieldModelForm): fields = ('name', 'slug', 'description', 'tags') -class ContactForm(CustomFieldModelForm): +class ContactForm(NetBoxModelForm): group = DynamicModelChoiceField( queryset=ContactGroup.objects.all(), required=False diff --git a/netbox/virtualization/forms/bulk_edit.py b/netbox/virtualization/forms/bulk_edit.py index 1e80e88e5..4232a87cd 100644 --- a/netbox/virtualization/forms/bulk_edit.py +++ b/netbox/virtualization/forms/bulk_edit.py @@ -3,8 +3,8 @@ from django import forms from dcim.choices import InterfaceModeChoices from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN from dcim.models import DeviceRole, Platform, Region, Site, SiteGroup -from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm from ipam.models import VLAN +from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import ( add_blank_choice, BulkEditNullBooleanSelect, BulkRenameForm, CommentField, DynamicModelChoiceField, @@ -23,7 +23,7 @@ __all__ = ( ) -class ClusterTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ClusterTypeBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ClusterType.objects.all(), widget=forms.MultipleHiddenInput @@ -37,7 +37,7 @@ class ClusterTypeBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['description'] -class ClusterGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ClusterGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), widget=forms.MultipleHiddenInput @@ -51,7 +51,7 @@ class ClusterGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['description'] -class ClusterBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class ClusterBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=Cluster.objects.all(), widget=forms.MultipleHiddenInput() @@ -95,7 +95,7 @@ class ClusterBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): ] -class VirtualMachineBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VirtualMachine.objects.all(), widget=forms.MultipleHiddenInput() @@ -150,7 +150,7 @@ class VirtualMachineBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm ] -class VMInterfaceBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=VMInterface.objects.all(), widget=forms.MultipleHiddenInput() diff --git a/netbox/virtualization/forms/bulk_import.py b/netbox/virtualization/forms/bulk_import.py index bd3279959..cefc2219d 100644 --- a/netbox/virtualization/forms/bulk_import.py +++ b/netbox/virtualization/forms/bulk_import.py @@ -1,6 +1,6 @@ from dcim.choices import InterfaceModeChoices from dcim.models import DeviceRole, Platform, Site -from extras.forms import CustomFieldModelCSVForm +from netbox.forms import NetBoxModelCSVForm from tenancy.models import Tenant from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField from virtualization.choices import * @@ -15,7 +15,7 @@ __all__ = ( ) -class ClusterTypeCSVForm(CustomFieldModelCSVForm): +class ClusterTypeCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -23,7 +23,7 @@ class ClusterTypeCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'description') -class ClusterGroupCSVForm(CustomFieldModelCSVForm): +class ClusterGroupCSVForm(NetBoxModelCSVForm): slug = SlugField() class Meta: @@ -31,7 +31,7 @@ class ClusterGroupCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'description') -class ClusterCSVForm(CustomFieldModelCSVForm): +class ClusterCSVForm(NetBoxModelCSVForm): type = CSVModelChoiceField( queryset=ClusterType.objects.all(), to_field_name='name', @@ -61,7 +61,7 @@ class ClusterCSVForm(CustomFieldModelCSVForm): fields = ('name', 'type', 'group', 'site', 'comments') -class VirtualMachineCSVForm(CustomFieldModelCSVForm): +class VirtualMachineCSVForm(NetBoxModelCSVForm): status = CSVChoiceField( choices=VirtualMachineStatusChoices, help_text='Operational status of device' @@ -99,7 +99,7 @@ class VirtualMachineCSVForm(CustomFieldModelCSVForm): ) -class VMInterfaceCSVForm(CustomFieldModelCSVForm): +class VMInterfaceCSVForm(NetBoxModelCSVForm): virtual_machine = CSVModelChoiceField( queryset=VirtualMachine.objects.all(), to_field_name='name' diff --git a/netbox/virtualization/forms/filtersets.py b/netbox/virtualization/forms/filtersets.py index 9ca8eba6e..292cd661d 100644 --- a/netbox/virtualization/forms/filtersets.py +++ b/netbox/virtualization/forms/filtersets.py @@ -2,7 +2,8 @@ from django import forms from django.utils.translation import gettext as _ from dcim.models import DeviceRole, Platform, Region, Site, SiteGroup -from extras.forms import CustomFieldModelFilterForm, LocalConfigContextFilterForm +from extras.forms import LocalConfigContextFilterForm +from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import ( DynamicModelMultipleChoiceField, StaticSelect, StaticSelectMultiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, @@ -19,17 +20,17 @@ __all__ = ( ) -class ClusterTypeFilterForm(CustomFieldModelFilterForm): +class ClusterTypeFilterForm(NetBoxModelFilterSetForm): model = ClusterType tag = TagFilterField(model) -class ClusterGroupFilterForm(CustomFieldModelFilterForm): +class ClusterGroupFilterForm(NetBoxModelFilterSetForm): model = ClusterGroup tag = TagFilterField(model) -class ClusterFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): +class ClusterFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = Cluster field_groups = [ ['q', 'tag'], @@ -71,7 +72,7 @@ class ClusterFilterForm(TenancyFilterForm, CustomFieldModelFilterForm): tag = TagFilterField(model) -class VirtualMachineFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, CustomFieldModelFilterForm): +class VirtualMachineFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, NetBoxModelFilterSetForm): model = VirtualMachine field_groups = [ ['q', 'tag'], @@ -151,7 +152,7 @@ class VirtualMachineFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, tag = TagFilterField(model) -class VMInterfaceFilterForm(CustomFieldModelFilterForm): +class VMInterfaceFilterForm(NetBoxModelFilterSetForm): model = VMInterface field_groups = [ ['q', 'tag'], diff --git a/netbox/virtualization/forms/models.py b/netbox/virtualization/forms/models.py index 624c9e87f..883fcd363 100644 --- a/netbox/virtualization/forms/models.py +++ b/netbox/virtualization/forms/models.py @@ -5,9 +5,9 @@ from django.core.exceptions import ValidationError from dcim.forms.common import InterfaceCommonForm from dcim.forms.models import INTERFACE_MODE_HELP_TEXT from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site, SiteGroup -from extras.forms import CustomFieldModelForm from extras.models import Tag from ipam.models import IPAddress, VLAN, VLANGroup +from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms import ( BootstrapMixin, CommentField, ConfirmationForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, @@ -26,7 +26,7 @@ __all__ = ( ) -class ClusterTypeForm(CustomFieldModelForm): +class ClusterTypeForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -40,7 +40,7 @@ class ClusterTypeForm(CustomFieldModelForm): ) -class ClusterGroupForm(CustomFieldModelForm): +class ClusterGroupForm(NetBoxModelForm): slug = SlugField() tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -54,7 +54,7 @@ class ClusterGroupForm(CustomFieldModelForm): ) -class ClusterForm(TenancyForm, CustomFieldModelForm): +class ClusterForm(TenancyForm, NetBoxModelForm): type = DynamicModelChoiceField( queryset=ClusterType.objects.all() ) @@ -171,7 +171,7 @@ class ClusterRemoveDevicesForm(ConfirmationForm): ) -class VirtualMachineForm(TenancyForm, CustomFieldModelForm): +class VirtualMachineForm(TenancyForm, NetBoxModelForm): cluster_group = DynamicModelChoiceField( queryset=ClusterGroup.objects.all(), required=False, @@ -271,7 +271,7 @@ class VirtualMachineForm(TenancyForm, CustomFieldModelForm): self.fields['primary_ip6'].widget.attrs['readonly'] = True -class VMInterfaceForm(InterfaceCommonForm, CustomFieldModelForm): +class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm): parent = DynamicModelChoiceField( queryset=VMInterface.objects.all(), required=False, diff --git a/netbox/wireless/forms/bulk_edit.py b/netbox/wireless/forms/bulk_edit.py index 9d07d09f0..147108d77 100644 --- a/netbox/wireless/forms/bulk_edit.py +++ b/netbox/wireless/forms/bulk_edit.py @@ -1,8 +1,8 @@ from django import forms from dcim.choices import LinkStatusChoices -from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm from ipam.models import VLAN +from netbox.forms import NetBoxModelBulkEditForm from utilities.forms import add_blank_choice, DynamicModelChoiceField from wireless.choices import * from wireless.constants import SSID_MAX_LENGTH @@ -15,7 +15,7 @@ __all__ = ( ) -class WirelessLANGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class WirelessLANGroupBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=WirelessLANGroup.objects.all(), widget=forms.MultipleHiddenInput @@ -33,7 +33,7 @@ class WirelessLANGroupBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditFo nullable_fields = ['parent', 'description'] -class WirelessLANBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class WirelessLANBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=WirelessLAN.objects.all(), widget=forms.MultipleHiddenInput @@ -72,7 +72,7 @@ class WirelessLANBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): nullable_fields = ['ssid', 'group', 'vlan', 'description', 'auth_type', 'auth_cipher', 'auth_psk'] -class WirelessLinkBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): +class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=WirelessLink.objects.all(), widget=forms.MultipleHiddenInput diff --git a/netbox/wireless/forms/bulk_import.py b/netbox/wireless/forms/bulk_import.py index aa79e1fc7..4b8acb385 100644 --- a/netbox/wireless/forms/bulk_import.py +++ b/netbox/wireless/forms/bulk_import.py @@ -1,7 +1,7 @@ from dcim.choices import LinkStatusChoices from dcim.models import Interface -from extras.forms import CustomFieldModelCSVForm from ipam.models import VLAN +from netbox.forms import NetBoxModelCSVForm from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField from wireless.choices import * from wireless.models import * @@ -13,7 +13,7 @@ __all__ = ( ) -class WirelessLANGroupCSVForm(CustomFieldModelCSVForm): +class WirelessLANGroupCSVForm(NetBoxModelCSVForm): parent = CSVModelChoiceField( queryset=WirelessLANGroup.objects.all(), required=False, @@ -27,7 +27,7 @@ class WirelessLANGroupCSVForm(CustomFieldModelCSVForm): fields = ('name', 'slug', 'parent', 'description') -class WirelessLANCSVForm(CustomFieldModelCSVForm): +class WirelessLANCSVForm(NetBoxModelCSVForm): group = CSVModelChoiceField( queryset=WirelessLANGroup.objects.all(), required=False, @@ -56,7 +56,7 @@ class WirelessLANCSVForm(CustomFieldModelCSVForm): fields = ('ssid', 'group', 'description', 'vlan', 'auth_type', 'auth_cipher', 'auth_psk') -class WirelessLinkCSVForm(CustomFieldModelCSVForm): +class WirelessLinkCSVForm(NetBoxModelCSVForm): status = CSVChoiceField( choices=LinkStatusChoices, help_text='Connection status' diff --git a/netbox/wireless/forms/filtersets.py b/netbox/wireless/forms/filtersets.py index 82df93e6c..3c46caf21 100644 --- a/netbox/wireless/forms/filtersets.py +++ b/netbox/wireless/forms/filtersets.py @@ -2,7 +2,7 @@ from django import forms from django.utils.translation import gettext as _ from dcim.choices import LinkStatusChoices -from extras.forms import CustomFieldModelFilterForm +from netbox.forms import NetBoxModelFilterSetForm from utilities.forms import add_blank_choice, DynamicModelMultipleChoiceField, StaticSelect, TagFilterField from wireless.choices import * from wireless.models import * @@ -14,7 +14,7 @@ __all__ = ( ) -class WirelessLANGroupFilterForm(CustomFieldModelFilterForm): +class WirelessLANGroupFilterForm(NetBoxModelFilterSetForm): model = WirelessLANGroup parent_id = DynamicModelMultipleChoiceField( queryset=WirelessLANGroup.objects.all(), @@ -24,7 +24,7 @@ class WirelessLANGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class WirelessLANFilterForm(CustomFieldModelFilterForm): +class WirelessLANFilterForm(NetBoxModelFilterSetForm): model = WirelessLAN field_groups = [ ('q', 'tag'), @@ -56,7 +56,7 @@ class WirelessLANFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class WirelessLinkFilterForm(CustomFieldModelFilterForm): +class WirelessLinkFilterForm(NetBoxModelFilterSetForm): model = WirelessLink ssid = forms.CharField( required=False, diff --git a/netbox/wireless/forms/models.py b/netbox/wireless/forms/models.py index 7687cb372..30a4a2352 100644 --- a/netbox/wireless/forms/models.py +++ b/netbox/wireless/forms/models.py @@ -1,7 +1,7 @@ from dcim.models import Device, Interface, Location, Site -from extras.forms import CustomFieldModelForm from extras.models import Tag from ipam.models import VLAN +from netbox.forms import NetBoxModelForm from utilities.forms import DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, StaticSelect from wireless.models import * @@ -12,7 +12,7 @@ __all__ = ( ) -class WirelessLANGroupForm(CustomFieldModelForm): +class WirelessLANGroupForm(NetBoxModelForm): parent = DynamicModelChoiceField( queryset=WirelessLANGroup.objects.all(), required=False @@ -30,7 +30,7 @@ class WirelessLANGroupForm(CustomFieldModelForm): ] -class WirelessLANForm(CustomFieldModelForm): +class WirelessLANForm(NetBoxModelForm): group = DynamicModelChoiceField( queryset=WirelessLANGroup.objects.all(), required=False @@ -61,7 +61,7 @@ class WirelessLANForm(CustomFieldModelForm): } -class WirelessLinkForm(CustomFieldModelForm): +class WirelessLinkForm(NetBoxModelForm): site_a = DynamicModelChoiceField( queryset=Site.objects.all(), required=False,