Add owner field to all applicable model forms

This commit is contained in:
Jeremy Stretch
2025-10-21 14:43:01 -04:00
parent 1fdfff6be2
commit e2163b9a3b
10 changed files with 124 additions and 181 deletions

View File

@@ -10,11 +10,11 @@ from circuits.constants import *
from circuits.models import * from circuits.models import *
from dcim.models import Interface, Site from dcim.models import Interface, Site
from ipam.models import ASN from ipam.models import ASN
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms import get_field_value from utilities.forms import get_field_value
from utilities.forms.fields import ( from utilities.forms.fields import (
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField,
) )
from utilities.forms.mixins import DistanceValidationMixin from utilities.forms.mixins import DistanceValidationMixin
from utilities.forms.rendering import FieldSet, InlineFields from utilities.forms.rendering import FieldSet, InlineFields
@@ -36,14 +36,13 @@ __all__ = (
) )
class ProviderForm(NetBoxModelForm): class ProviderForm(PrimaryModelForm):
slug = SlugField() slug = SlugField()
asns = DynamicModelMultipleChoiceField( asns = DynamicModelMultipleChoiceField(
queryset=ASN.objects.all(), queryset=ASN.objects.all(),
label=_('ASNs'), label=_('ASNs'),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'asns', 'description', 'tags'), FieldSet('name', 'slug', 'asns', 'description', 'tags'),
@@ -56,14 +55,13 @@ class ProviderForm(NetBoxModelForm):
] ]
class ProviderAccountForm(NetBoxModelForm): class ProviderAccountForm(PrimaryModelForm):
provider = DynamicModelChoiceField( provider = DynamicModelChoiceField(
label=_('Provider'), label=_('Provider'),
queryset=Provider.objects.all(), queryset=Provider.objects.all(),
selector=True, selector=True,
quick_add=True quick_add=True
) )
comments = CommentField()
class Meta: class Meta:
model = ProviderAccount model = ProviderAccount
@@ -72,14 +70,13 @@ class ProviderAccountForm(NetBoxModelForm):
] ]
class ProviderNetworkForm(NetBoxModelForm): class ProviderNetworkForm(PrimaryModelForm):
provider = DynamicModelChoiceField( provider = DynamicModelChoiceField(
label=_('Provider'), label=_('Provider'),
queryset=Provider.objects.all(), queryset=Provider.objects.all(),
selector=True, selector=True,
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('provider', 'name', 'service_id', 'description', 'tags'), FieldSet('provider', 'name', 'service_id', 'description', 'tags'),
@@ -92,9 +89,7 @@ class ProviderNetworkForm(NetBoxModelForm):
] ]
class CircuitTypeForm(NetBoxModelForm): class CircuitTypeForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'color', 'description', 'owner', 'tags'), FieldSet('name', 'slug', 'color', 'description', 'owner', 'tags'),
) )
@@ -106,7 +101,7 @@ class CircuitTypeForm(NetBoxModelForm):
] ]
class CircuitForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm): class CircuitForm(DistanceValidationMixin, TenancyForm, PrimaryModelForm):
provider = DynamicModelChoiceField( provider = DynamicModelChoiceField(
label=_('Provider'), label=_('Provider'),
queryset=Provider.objects.all(), queryset=Provider.objects.all(),
@@ -125,7 +120,6 @@ class CircuitForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
queryset=CircuitType.objects.all(), queryset=CircuitType.objects.all(),
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -233,9 +227,7 @@ class CircuitTerminationForm(NetBoxModelForm):
self.instance.termination = self.cleaned_data.get('termination') self.instance.termination = self.cleaned_data.get('termination')
class CircuitGroupForm(TenancyForm, NetBoxModelForm): class CircuitGroupForm(TenancyForm, OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Circuit Group')), FieldSet('name', 'slug', 'description', 'tags', name=_('Circuit Group')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')), FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
@@ -307,9 +299,7 @@ class CircuitGroupAssignmentForm(NetBoxModelForm):
self.instance.member = self.cleaned_data.get('member') self.instance.member = self.cleaned_data.get('member')
class VirtualCircuitTypeForm(NetBoxModelForm): class VirtualCircuitTypeForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'color', 'description', 'tags'), FieldSet('name', 'slug', 'color', 'description', 'tags'),
) )
@@ -321,7 +311,7 @@ class VirtualCircuitTypeForm(NetBoxModelForm):
] ]
class VirtualCircuitForm(TenancyForm, NetBoxModelForm): class VirtualCircuitForm(TenancyForm, PrimaryModelForm):
provider_network = DynamicModelChoiceField( provider_network = DynamicModelChoiceField(
label=_('Provider network'), label=_('Provider network'),
queryset=ProviderNetwork.objects.all(), queryset=ProviderNetwork.objects.all(),
@@ -336,7 +326,6 @@ class VirtualCircuitForm(TenancyForm, NetBoxModelForm):
queryset=VirtualCircuitType.objects.all(), queryset=VirtualCircuitType.objects.all(),
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(

View File

@@ -9,11 +9,11 @@ from django.utils.translation import gettext_lazy as _
from core.forms.mixins import SyncedDataMixin from core.forms.mixins import SyncedDataMixin
from core.models import * from core.models import *
from netbox.config import get_config, PARAMS from netbox.config import get_config, PARAMS
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm, PrimaryModelForm
from netbox.registry import registry from netbox.registry import registry
from netbox.utils import get_data_backend_choices from netbox.utils import get_data_backend_choices
from utilities.forms import get_field_value from utilities.forms import get_field_value
from utilities.forms.fields import CommentField, JSONField from utilities.forms.fields import JSONField
from utilities.forms.rendering import FieldSet from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import HTMXSelect from utilities.forms.widgets import HTMXSelect
@@ -26,12 +26,11 @@ __all__ = (
EMPTY_VALUES = ('', None, [], ()) EMPTY_VALUES = ('', None, [], ())
class DataSourceForm(NetBoxModelForm): class DataSourceForm(PrimaryModelForm):
type = forms.ChoiceField( type = forms.ChoiceField(
choices=get_data_backend_choices, choices=get_data_backend_choices,
widget=HTMXSelect() widget=HTMXSelect()
) )
comments = CommentField()
class Meta: class Meta:
model = DataSource model = DataSource

View File

@@ -10,13 +10,13 @@ from dcim.models import *
from extras.models import ConfigTemplate from extras.models import ConfigTemplate
from ipam.choices import VLANQinQRoleChoices from ipam.choices import VLANQinQRoleChoices
from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF
from netbox.forms import NetBoxModelForm from netbox.forms import NestedGroupModelForm, NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from netbox.forms.mixins import ChangelogMessageMixin from netbox.forms.mixins import ChangelogMessageMixin
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from users.models import User from users.models import User
from utilities.forms import add_blank_choice, get_field_value from utilities.forms import add_blank_choice, get_field_value
from utilities.forms.fields import ( from utilities.forms.fields import (
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
) )
from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups
from utilities.forms.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK from utilities.forms.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK
@@ -75,14 +75,12 @@ __all__ = (
) )
class RegionForm(NetBoxModelForm): class RegionForm(NestedGroupModelForm):
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=Region.objects.all(), queryset=Region.objects.all(),
required=False required=False
) )
slug = SlugField()
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags'), FieldSet('parent', 'name', 'slug', 'description', 'tags'),
@@ -95,14 +93,12 @@ class RegionForm(NetBoxModelForm):
) )
class SiteGroupForm(NetBoxModelForm): class SiteGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=SiteGroup.objects.all(), queryset=SiteGroup.objects.all(),
required=False required=False
) )
slug = SlugField()
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags'), FieldSet('parent', 'name', 'slug', 'description', 'tags'),
@@ -115,7 +111,7 @@ class SiteGroupForm(NetBoxModelForm):
) )
class SiteForm(TenancyForm, NetBoxModelForm): class SiteForm(TenancyForm, PrimaryModelForm):
region = DynamicModelChoiceField( region = DynamicModelChoiceField(
label=_('Region'), label=_('Region'),
queryset=Region.objects.all(), queryset=Region.objects.all(),
@@ -139,7 +135,6 @@ class SiteForm(TenancyForm, NetBoxModelForm):
choices=add_blank_choice(TimeZoneFormField().choices), choices=add_blank_choice(TimeZoneFormField().choices),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -170,7 +165,7 @@ class SiteForm(TenancyForm, NetBoxModelForm):
} }
class LocationForm(TenancyForm, NetBoxModelForm): class LocationForm(TenancyForm, NestedGroupModelForm):
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
label=_('Site'), label=_('Site'),
queryset=Site.objects.all(), queryset=Site.objects.all(),
@@ -184,8 +179,6 @@ class LocationForm(TenancyForm, NetBoxModelForm):
'site_id': '$site' 'site_id': '$site'
} }
) )
slug = SlugField()
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('site', 'parent', 'name', 'slug', 'status', 'facility', 'description', 'tags', name=_('Location')), FieldSet('site', 'parent', 'name', 'slug', 'status', 'facility', 'description', 'tags', name=_('Location')),
@@ -200,9 +193,7 @@ class LocationForm(TenancyForm, NetBoxModelForm):
) )
class RackRoleForm(NetBoxModelForm): class RackRoleForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Rack Role')), FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Rack Role')),
) )
@@ -214,13 +205,12 @@ class RackRoleForm(NetBoxModelForm):
] ]
class RackTypeForm(NetBoxModelForm): class RackTypeForm(PrimaryModelForm):
manufacturer = DynamicModelChoiceField( manufacturer = DynamicModelChoiceField(
label=_('Manufacturer'), label=_('Manufacturer'),
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
quick_add=True quick_add=True
) )
comments = CommentField()
slug = SlugField( slug = SlugField(
label=_('Slug'), label=_('Slug'),
slug_source='model' slug_source='model'
@@ -246,7 +236,7 @@ class RackTypeForm(NetBoxModelForm):
] ]
class RackForm(TenancyForm, NetBoxModelForm): class RackForm(TenancyForm, PrimaryModelForm):
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
label=_('Site'), label=_('Site'),
queryset=Site.objects.all(), queryset=Site.objects.all(),
@@ -271,7 +261,6 @@ class RackForm(TenancyForm, NetBoxModelForm):
required=False, required=False,
help_text=_("Select a pre-defined rack type, or set physical characteristics below.") help_text=_("Select a pre-defined rack type, or set physical characteristics below.")
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -333,7 +322,6 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
label=_('User'), label=_('User'),
queryset=User.objects.order_by('username') queryset=User.objects.order_by('username')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('rack', 'units', 'status', 'user', 'description', 'tags', name=_('Reservation')), FieldSet('rack', 'units', 'status', 'user', 'description', 'tags', name=_('Reservation')),
@@ -347,9 +335,7 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
] ]
class ManufacturerForm(NetBoxModelForm): class ManufacturerForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Manufacturer')), FieldSet('name', 'slug', 'description', 'tags', name=_('Manufacturer')),
) )
@@ -361,7 +347,7 @@ class ManufacturerForm(NetBoxModelForm):
] ]
class DeviceTypeForm(NetBoxModelForm): class DeviceTypeForm(PrimaryModelForm):
manufacturer = DynamicModelChoiceField( manufacturer = DynamicModelChoiceField(
label=_('Manufacturer'), label=_('Manufacturer'),
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
@@ -380,7 +366,6 @@ class DeviceTypeForm(NetBoxModelForm):
label=_('Slug'), label=_('Slug'),
slug_source='model' slug_source='model'
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('manufacturer', 'model', 'slug', 'default_platform', 'description', 'tags', name=_('Device Type')), FieldSet('manufacturer', 'model', 'slug', 'default_platform', 'description', 'tags', name=_('Device Type')),
@@ -408,13 +393,12 @@ class DeviceTypeForm(NetBoxModelForm):
} }
class ModuleTypeProfileForm(NetBoxModelForm): class ModuleTypeProfileForm(PrimaryModelForm):
schema = JSONField( schema = JSONField(
label=_('Schema'), label=_('Schema'),
required=False, required=False,
help_text=_("Enter a valid JSON schema to define supported attributes.") help_text=_("Enter a valid JSON schema to define supported attributes.")
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'schema', 'tags', name=_('Profile')), FieldSet('name', 'description', 'schema', 'tags', name=_('Profile')),
@@ -427,7 +411,7 @@ class ModuleTypeProfileForm(NetBoxModelForm):
] ]
class ModuleTypeForm(NetBoxModelForm): class ModuleTypeForm(PrimaryModelForm):
profile = forms.ModelChoiceField( profile = forms.ModelChoiceField(
queryset=ModuleTypeProfile.objects.all(), queryset=ModuleTypeProfile.objects.all(),
label=_('Profile'), label=_('Profile'),
@@ -438,7 +422,6 @@ class ModuleTypeForm(NetBoxModelForm):
label=_('Manufacturer'), label=_('Manufacturer'),
queryset=Manufacturer.objects.all() queryset=Manufacturer.objects.all()
) )
comments = CommentField()
@property @property
def fieldsets(self): def fieldsets(self):
@@ -507,19 +490,17 @@ class ModuleTypeForm(NetBoxModelForm):
return super()._post_clean() return super()._post_clean()
class DeviceRoleForm(NetBoxModelForm): class DeviceRoleForm(NestedGroupModelForm):
config_template = DynamicModelChoiceField( config_template = DynamicModelChoiceField(
label=_('Config template'), label=_('Config template'),
queryset=ConfigTemplate.objects.all(), queryset=ConfigTemplate.objects.all(),
required=False required=False
) )
slug = SlugField()
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=DeviceRole.objects.all(), queryset=DeviceRole.objects.all(),
required=False, required=False,
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -535,7 +516,7 @@ class DeviceRoleForm(NetBoxModelForm):
] ]
class PlatformForm(NetBoxModelForm): class PlatformForm(NestedGroupModelForm):
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
@@ -556,7 +537,6 @@ class PlatformForm(NetBoxModelForm):
label=_('Slug'), label=_('Slug'),
max_length=64 max_length=64
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -571,7 +551,7 @@ class PlatformForm(NetBoxModelForm):
] ]
class DeviceForm(TenancyForm, NetBoxModelForm): class DeviceForm(TenancyForm, PrimaryModelForm):
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
label=_('Site'), label=_('Site'),
queryset=Site.objects.all(), queryset=Site.objects.all(),
@@ -641,7 +621,6 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
'site_id': ['$site', 'null'] 'site_id': ['$site', 'null']
}, },
) )
comments = CommentField()
local_context_data = JSONField( local_context_data = JSONField(
required=False, required=False,
label='' label=''
@@ -742,7 +721,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
self.fields['position'].widget.choices = [(position, f'U{position}')] self.fields['position'].widget.choices = [(position, f'U{position}')]
class ModuleForm(ModuleCommonForm, NetBoxModelForm): class ModuleForm(ModuleCommonForm, PrimaryModelForm):
device = DynamicModelChoiceField( device = DynamicModelChoiceField(
label=_('Device'), label=_('Device'),
queryset=Device.objects.all(), queryset=Device.objects.all(),
@@ -765,7 +744,6 @@ class ModuleForm(ModuleCommonForm, NetBoxModelForm):
}, },
selector=True selector=True
) )
comments = CommentField()
replicate_components = forms.BooleanField( replicate_components = forms.BooleanField(
label=_('Replicate components'), label=_('Replicate components'),
required=False, required=False,
@@ -809,7 +787,7 @@ def get_termination_type_choices():
]) ])
class CableForm(TenancyForm, NetBoxModelForm): class CableForm(TenancyForm, PrimaryModelForm):
a_terminations_type = forms.ChoiceField( a_terminations_type = forms.ChoiceField(
choices=get_termination_type_choices, choices=get_termination_type_choices,
required=False, required=False,
@@ -822,7 +800,6 @@ class CableForm(TenancyForm, NetBoxModelForm):
widget=HTMXSelect(), widget=HTMXSelect(),
label=_('Type') label=_('Type')
) )
comments = CommentField()
class Meta: class Meta:
model = Cable model = Cable
@@ -832,7 +809,7 @@ class CableForm(TenancyForm, NetBoxModelForm):
] ]
class PowerPanelForm(NetBoxModelForm): class PowerPanelForm(PrimaryModelForm):
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
label=_('Site'), label=_('Site'),
queryset=Site.objects.all(), queryset=Site.objects.all(),
@@ -846,7 +823,6 @@ class PowerPanelForm(NetBoxModelForm):
'site_id': '$site' 'site_id': '$site'
} }
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('site', 'location', 'name', 'description', 'tags', name=_('Power Panel')), FieldSet('site', 'location', 'name', 'description', 'tags', name=_('Power Panel')),
@@ -859,7 +835,7 @@ class PowerPanelForm(NetBoxModelForm):
] ]
class PowerFeedForm(TenancyForm, NetBoxModelForm): class PowerFeedForm(TenancyForm, PrimaryModelForm):
power_panel = DynamicModelChoiceField( power_panel = DynamicModelChoiceField(
label=_('Power panel'), label=_('Power panel'),
queryset=PowerPanel.objects.all(), queryset=PowerPanel.objects.all(),
@@ -872,7 +848,6 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
required=False, required=False,
selector=True selector=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -895,13 +870,12 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
# Virtual chassis # Virtual chassis
# #
class VirtualChassisForm(NetBoxModelForm): class VirtualChassisForm(PrimaryModelForm):
master = forms.ModelChoiceField( master = forms.ModelChoiceField(
label=_('Master'), label=_('Master'),
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,
) )
comments = CommentField()
class Meta: class Meta:
model = VirtualChassis model = VirtualChassis
@@ -1829,9 +1803,7 @@ class InventoryItemForm(DeviceComponentForm):
self.instance.component = None self.instance.component = None
class InventoryItemRoleForm(NetBoxModelForm): class InventoryItemRoleForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Inventory Item Role')), FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Inventory Item Role')),
) )
@@ -1843,7 +1815,7 @@ class InventoryItemRoleForm(NetBoxModelForm):
] ]
class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm): class VirtualDeviceContextForm(TenancyForm, PrimaryModelForm):
device = DynamicModelChoiceField( device = DynamicModelChoiceField(
label=_('Device'), label=_('Device'),
queryset=Device.objects.all(), queryset=Device.objects.all(),
@@ -1888,7 +1860,7 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
# Addressing # Addressing
# #
class MACAddressForm(NetBoxModelForm): class MACAddressForm(PrimaryModelForm):
mac_address = forms.CharField( mac_address = forms.CharField(
required=True, required=True,
label=_('MAC address') label=_('MAC address')

View File

@@ -12,8 +12,8 @@ from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site
from extras.choices import * from extras.choices import *
from extras.models import * from extras.models import *
from netbox.events import get_event_type_choices from netbox.events import get_event_type_choices
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm, PrimaryModelForm
from netbox.forms.mixins import ChangelogMessageMixin from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from users.models import Group, User from users.models import Group, User
from utilities.forms import get_field_value from utilities.forms import get_field_value
@@ -47,7 +47,7 @@ __all__ = (
) )
class CustomFieldForm(ChangelogMessageMixin, forms.ModelForm): class CustomFieldForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('custom_fields'), queryset=ObjectType.objects.with_feature('custom_fields'),
@@ -166,7 +166,7 @@ class CustomFieldForm(ChangelogMessageMixin, forms.ModelForm):
del self.fields['choice_set'] del self.fields['choice_set']
class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm): class CustomFieldChoiceSetForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
# TODO: The extra_choices field definition diverge from the CustomFieldChoiceSet model # TODO: The extra_choices field definition diverge from the CustomFieldChoiceSet model
extra_choices = forms.CharField( extra_choices = forms.CharField(
widget=ChoicesWidget(), widget=ChoicesWidget(),
@@ -219,7 +219,7 @@ class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
return data return data
class CustomLinkForm(ChangelogMessageMixin, forms.ModelForm): class CustomLinkForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('custom_links') queryset=ObjectType.objects.with_feature('custom_links')
@@ -251,7 +251,7 @@ class CustomLinkForm(ChangelogMessageMixin, forms.ModelForm):
} }
class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm): class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('export_templates') queryset=ObjectType.objects.with_feature('export_templates')
@@ -293,7 +293,7 @@ class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm
return self.cleaned_data return self.cleaned_data
class SavedFilterForm(ChangelogMessageMixin, forms.ModelForm): class SavedFilterForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
slug = SlugField() slug = SlugField()
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
@@ -427,7 +427,7 @@ class SubscriptionForm(forms.ModelForm):
fields = ('object_type', 'object_id') fields = ('object_type', 'object_id')
class WebhookForm(NetBoxModelForm): class WebhookForm(OwnerMixin, NetBoxModelForm):
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Webhook')), FieldSet('name', 'description', 'tags', name=_('Webhook')),
@@ -447,7 +447,7 @@ class WebhookForm(NetBoxModelForm):
} }
class EventRuleForm(NetBoxModelForm): class EventRuleForm(OwnerMixin, NetBoxModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('event_rules'), queryset=ObjectType.objects.with_feature('event_rules'),
@@ -563,7 +563,7 @@ class EventRuleForm(NetBoxModelForm):
return self.cleaned_data return self.cleaned_data
class TagForm(ChangelogMessageMixin, forms.ModelForm): class TagForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
slug = SlugField() slug = SlugField()
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
@@ -586,7 +586,7 @@ class TagForm(ChangelogMessageMixin, forms.ModelForm):
] ]
class ConfigContextProfileForm(SyncedDataMixin, NetBoxModelForm): class ConfigContextProfileForm(SyncedDataMixin, PrimaryModelForm):
schema = JSONField( schema = JSONField(
label=_('Schema'), label=_('Schema'),
required=False, required=False,
@@ -611,7 +611,7 @@ class ConfigContextProfileForm(SyncedDataMixin, NetBoxModelForm):
) )
class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm): class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
profile = DynamicModelChoiceField( profile = DynamicModelChoiceField(
label=_('Profile'), label=_('Profile'),
queryset=ConfigContextProfile.objects.all(), queryset=ConfigContextProfile.objects.all(),
@@ -728,7 +728,7 @@ class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm)
return self.cleaned_data return self.cleaned_data
class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm): class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
tags = DynamicModelMultipleChoiceField( tags = DynamicModelMultipleChoiceField(
label=_('Tags'), label=_('Tags'),
queryset=Tag.objects.all(), queryset=Tag.objects.all(),

View File

@@ -9,13 +9,13 @@ from ipam.choices import *
from ipam.constants import * from ipam.constants import *
from ipam.formfields import IPNetworkFormField from ipam.formfields import IPNetworkFormField
from ipam.models import * from ipam.models import *
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.exceptions import PermissionsViolation from utilities.exceptions import PermissionsViolation
from utilities.forms import add_blank_choice from utilities.forms import add_blank_choice
from utilities.forms.fields import ( from utilities.forms.fields import (
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
NumericRangeArrayField, SlugField NumericRangeArrayField,
) )
from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups
from utilities.forms.utils import get_field_value from utilities.forms.utils import get_field_value
@@ -49,7 +49,7 @@ __all__ = (
) )
class VRFForm(TenancyForm, NetBoxModelForm): class VRFForm(TenancyForm, PrimaryModelForm):
import_targets = DynamicModelMultipleChoiceField( import_targets = DynamicModelMultipleChoiceField(
label=_('Import targets'), label=_('Import targets'),
queryset=RouteTarget.objects.all(), queryset=RouteTarget.objects.all(),
@@ -60,7 +60,6 @@ class VRFForm(TenancyForm, NetBoxModelForm):
queryset=RouteTarget.objects.all(), queryset=RouteTarget.objects.all(),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'rd', 'enforce_unique', 'description', 'tags', name=_('VRF')), FieldSet('name', 'rd', 'enforce_unique', 'description', 'tags', name=_('VRF')),
@@ -79,12 +78,11 @@ class VRFForm(TenancyForm, NetBoxModelForm):
} }
class RouteTargetForm(TenancyForm, NetBoxModelForm): class RouteTargetForm(TenancyForm, PrimaryModelForm):
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Route Target')), FieldSet('name', 'description', 'tags', name=_('Route Target')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')), FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
) )
comments = CommentField()
class Meta: class Meta:
model = RouteTarget model = RouteTarget
@@ -93,9 +91,7 @@ class RouteTargetForm(TenancyForm, NetBoxModelForm):
] ]
class RIRForm(NetBoxModelForm): class RIRForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'is_private', 'description', 'tags', name=_('RIR')), FieldSet('name', 'slug', 'is_private', 'description', 'tags', name=_('RIR')),
) )
@@ -107,13 +103,12 @@ class RIRForm(NetBoxModelForm):
] ]
class AggregateForm(TenancyForm, NetBoxModelForm): class AggregateForm(TenancyForm, PrimaryModelForm):
rir = DynamicModelChoiceField( rir = DynamicModelChoiceField(
queryset=RIR.objects.all(), queryset=RIR.objects.all(),
label=_('RIR'), label=_('RIR'),
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('prefix', 'rir', 'date_added', 'description', 'tags', name=_('Aggregate')), FieldSet('prefix', 'rir', 'date_added', 'description', 'tags', name=_('Aggregate')),
@@ -130,13 +125,12 @@ class AggregateForm(TenancyForm, NetBoxModelForm):
} }
class ASNRangeForm(TenancyForm, NetBoxModelForm): class ASNRangeForm(TenancyForm, OrganizationalModelForm):
rir = DynamicModelChoiceField( rir = DynamicModelChoiceField(
queryset=RIR.objects.all(), queryset=RIR.objects.all(),
label=_('RIR'), label=_('RIR'),
quick_add=True quick_add=True
) )
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'rir', 'start', 'end', 'description', 'tags', name=_('ASN Range')), FieldSet('name', 'slug', 'rir', 'start', 'end', 'description', 'tags', name=_('ASN Range')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')), FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
@@ -149,7 +143,7 @@ class ASNRangeForm(TenancyForm, NetBoxModelForm):
] ]
class ASNForm(TenancyForm, NetBoxModelForm): class ASNForm(TenancyForm, PrimaryModelForm):
rir = DynamicModelChoiceField( rir = DynamicModelChoiceField(
queryset=RIR.objects.all(), queryset=RIR.objects.all(),
label=_('RIR'), label=_('RIR'),
@@ -160,7 +154,6 @@ class ASNForm(TenancyForm, NetBoxModelForm):
label=_('Sites'), label=_('Sites'),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('asn', 'rir', 'sites', 'description', 'tags', name=_('ASN')), FieldSet('asn', 'rir', 'sites', 'description', 'tags', name=_('ASN')),
@@ -188,9 +181,7 @@ class ASNForm(TenancyForm, NetBoxModelForm):
return instance return instance
class RoleForm(NetBoxModelForm): class RoleForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'weight', 'description', 'tags', name=_('Role')), FieldSet('name', 'slug', 'weight', 'description', 'tags', name=_('Role')),
) )
@@ -202,7 +193,7 @@ class RoleForm(NetBoxModelForm):
] ]
class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm): class PrefixForm(TenancyForm, ScopedForm, PrimaryModelForm):
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
@@ -223,7 +214,6 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
required=False, required=False,
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -250,7 +240,7 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
self.fields['vlan'].widget.attrs.pop('data-dynamic-params', None) self.fields['vlan'].widget.attrs.pop('data-dynamic-params', None)
class IPRangeForm(TenancyForm, NetBoxModelForm): class IPRangeForm(TenancyForm, PrimaryModelForm):
vrf = DynamicModelChoiceField( vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(), queryset=VRF.objects.all(),
required=False, required=False,
@@ -262,7 +252,6 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
required=False, required=False,
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(
@@ -280,7 +269,7 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
] ]
class IPAddressForm(TenancyForm, NetBoxModelForm): class IPAddressForm(TenancyForm, PrimaryModelForm):
interface = DynamicModelChoiceField( interface = DynamicModelChoiceField(
queryset=Interface.objects.all(), queryset=Interface.objects.all(),
required=False, required=False,
@@ -324,7 +313,6 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
required=False, required=False,
label=_('Make this the out-of-band IP for the device') label=_('Make this the out-of-band IP for the device')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('address', 'status', 'role', 'vrf', 'dns_name', 'description', 'tags', name=_('IP Address')), FieldSet('address', 'status', 'role', 'vrf', 'dns_name', 'description', 'tags', name=_('IP Address')),
@@ -494,7 +482,7 @@ class IPAddressAssignForm(forms.Form):
) )
class FHRPGroupForm(NetBoxModelForm): class FHRPGroupForm(PrimaryModelForm):
# Optionally create a new IPAddress along with the FHRPGroup # Optionally create a new IPAddress along with the FHRPGroup
ip_vrf = DynamicModelChoiceField( ip_vrf = DynamicModelChoiceField(
@@ -511,7 +499,6 @@ class FHRPGroupForm(NetBoxModelForm):
required=False, required=False,
label=_('Status') label=_('Status')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('protocol', 'group_id', 'name', 'description', 'tags', name=_('FHRP Group')), FieldSet('protocol', 'group_id', 'name', 'description', 'tags', name=_('FHRP Group')),
@@ -599,8 +586,7 @@ class FHRPGroupAssignmentForm(forms.ModelForm):
return group return group
class VLANGroupForm(TenancyForm, NetBoxModelForm): class VLANGroupForm(TenancyForm, OrganizationalModelForm):
slug = SlugField()
vid_ranges = NumericRangeArrayField( vid_ranges = NumericRangeArrayField(
label=_('VLAN IDs') label=_('VLAN IDs')
) )
@@ -662,7 +648,7 @@ class VLANGroupForm(TenancyForm, NetBoxModelForm):
self.instance.scope = self.cleaned_data.get('scope') self.instance.scope = self.cleaned_data.get('scope')
class VLANForm(TenancyForm, NetBoxModelForm): class VLANForm(TenancyForm, PrimaryModelForm):
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(), queryset=VLANGroup.objects.all(),
required=False, required=False,
@@ -698,7 +684,6 @@ class VLANForm(TenancyForm, NetBoxModelForm):
'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE, 'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE,
} }
) )
comments = CommentField()
class Meta: class Meta:
model = VLAN model = VLAN
@@ -708,7 +693,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
] ]
class VLANTranslationPolicyForm(NetBoxModelForm): class VLANTranslationPolicyForm(PrimaryModelForm):
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'tags', name=_('VLAN Translation Policy')), FieldSet('name', 'description', 'tags', name=_('VLAN Translation Policy')),
@@ -739,7 +724,7 @@ class VLANTranslationRuleForm(NetBoxModelForm):
] ]
class ServiceTemplateForm(NetBoxModelForm): class ServiceTemplateForm(PrimaryModelForm):
ports = NumericArrayField( ports = NumericArrayField(
label=_('Ports'), label=_('Ports'),
base_field=forms.IntegerField( base_field=forms.IntegerField(
@@ -748,7 +733,6 @@ class ServiceTemplateForm(NetBoxModelForm):
), ),
help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.") help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.")
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'protocol', 'ports', 'description', 'tags', name=_('Application Service Template')), FieldSet('name', 'protocol', 'ports', 'description', 'tags', name=_('Application Service Template')),
@@ -759,7 +743,7 @@ class ServiceTemplateForm(NetBoxModelForm):
fields = ('name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags') fields = ('name', 'protocol', 'ports', 'description', 'owner', 'comments', 'tags')
class ServiceForm(NetBoxModelForm): class ServiceForm(PrimaryModelForm):
parent_object_type = ContentTypeChoiceField( parent_object_type = ContentTypeChoiceField(
queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS), queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS),
widget=HTMXSelect(), widget=HTMXSelect(),
@@ -786,7 +770,6 @@ class ServiceForm(NetBoxModelForm):
required=False, required=False,
label=_('IP Addresses'), label=_('IP Addresses'),
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(

View File

@@ -4,11 +4,15 @@ from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from extras.choices import * from extras.choices import *
from utilities.forms.fields import CommentField, SlugField
from utilities.forms.mixins import CheckLastUpdatedMixin from utilities.forms.mixins import CheckLastUpdatedMixin
from .mixins import ChangelogMessageMixin, CustomFieldsMixin, OwnerMixin, TagsMixin from .mixins import ChangelogMessageMixin, CustomFieldsMixin, OwnerMixin, TagsMixin
__all__ = ( __all__ = (
'NestedGroupModelForm',
'NetBoxModelForm', 'NetBoxModelForm',
'OrganizationalModelForm',
'PrimaryModelForm',
) )
@@ -16,7 +20,6 @@ class NetBoxModelForm(
ChangelogMessageMixin, ChangelogMessageMixin,
CheckLastUpdatedMixin, CheckLastUpdatedMixin,
CustomFieldsMixin, CustomFieldsMixin,
OwnerMixin,
TagsMixin, TagsMixin,
forms.ModelForm forms.ModelForm
): ):
@@ -74,3 +77,25 @@ class NetBoxModelForm(
self.instance._m2m_values[field.name] = list(self.cleaned_data[field.name]) self.instance._m2m_values[field.name] = list(self.cleaned_data[field.name])
return super()._post_clean() return super()._post_clean()
class PrimaryModelForm(OwnerMixin, NetBoxModelForm):
"""
Form for models which inherit from PrimaryModel.
"""
comments = CommentField()
class OrganizationalModelForm(OwnerMixin, NetBoxModelForm):
"""
Form for models which inherit from OrganizationalModel.
"""
slug = SlugField()
class NestedGroupModelForm(OwnerMixin, NetBoxModelForm):
"""
Form for models which inherit from NestedGroupModel.
"""
slug = SlugField()
comments = CommentField()

View File

@@ -1,9 +1,9 @@
from django import forms from django import forms
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from netbox.forms import NetBoxModelForm from netbox.forms import NestedGroupModelForm, NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from tenancy.models import * from tenancy.models import *
from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField
from utilities.forms.rendering import FieldSet, ObjectAttribute from utilities.forms.rendering import FieldSet, ObjectAttribute
__all__ = ( __all__ = (
@@ -20,14 +20,12 @@ __all__ = (
# Tenants # Tenants
# #
class TenantGroupForm(NetBoxModelForm): class TenantGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
required=False required=False
) )
slug = SlugField()
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Tenant Group')), FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Tenant Group')),
@@ -40,14 +38,13 @@ class TenantGroupForm(NetBoxModelForm):
] ]
class TenantForm(NetBoxModelForm): class TenantForm(PrimaryModelForm):
slug = SlugField() slug = SlugField()
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
label=_('Group'), label=_('Group'),
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'group', 'description', 'tags', name=_('Tenant')), FieldSet('name', 'slug', 'group', 'description', 'tags', name=_('Tenant')),
@@ -64,14 +61,12 @@ class TenantForm(NetBoxModelForm):
# Contacts # Contacts
# #
class ContactGroupForm(NetBoxModelForm): class ContactGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=ContactGroup.objects.all(), queryset=ContactGroup.objects.all(),
required=False required=False
) )
slug = SlugField()
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Contact Group')), FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Contact Group')),
@@ -82,9 +77,7 @@ class ContactGroupForm(NetBoxModelForm):
fields = ('parent', 'name', 'slug', 'description', 'owner', 'comments', 'tags') fields = ('parent', 'name', 'slug', 'description', 'owner', 'comments', 'tags')
class ContactRoleForm(NetBoxModelForm): class ContactRoleForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Contact Role')), FieldSet('name', 'slug', 'description', 'tags', name=_('Contact Role')),
) )
@@ -94,7 +87,7 @@ class ContactRoleForm(NetBoxModelForm):
fields = ('name', 'slug', 'description', 'owner', 'tags') fields = ('name', 'slug', 'description', 'owner', 'tags')
class ContactForm(NetBoxModelForm): class ContactForm(PrimaryModelForm):
groups = DynamicModelMultipleChoiceField( groups = DynamicModelMultipleChoiceField(
label=_('Groups'), label=_('Groups'),
queryset=ContactGroup.objects.all(), queryset=ContactGroup.objects.all(),
@@ -105,7 +98,6 @@ class ContactForm(NetBoxModelForm):
assume_scheme='https', assume_scheme='https',
required=False, required=False,
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet( FieldSet(

View File

@@ -10,12 +10,10 @@ from dcim.models import Device, DeviceRole, MACAddress, Platform, Rack, Region,
from extras.models import ConfigTemplate from extras.models import ConfigTemplate
from ipam.choices import VLANQinQRoleChoices from ipam.choices import VLANQinQRoleChoices
from ipam.models import IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF from ipam.models import IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms import ConfirmationForm from utilities.forms import ConfirmationForm
from utilities.forms.fields import ( from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, SlugField,
)
from utilities.forms.rendering import FieldSet from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import HTMXSelect from utilities.forms.widgets import HTMXSelect
from virtualization.models import * from virtualization.models import *
@@ -32,9 +30,7 @@ __all__ = (
) )
class ClusterTypeForm(NetBoxModelForm): class ClusterTypeForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Type')), FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Type')),
) )
@@ -46,9 +42,7 @@ class ClusterTypeForm(NetBoxModelForm):
) )
class ClusterGroupForm(NetBoxModelForm): class ClusterGroupForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Group')), FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Group')),
) )
@@ -60,7 +54,7 @@ class ClusterGroupForm(NetBoxModelForm):
) )
class ClusterForm(TenancyForm, ScopedForm, NetBoxModelForm): class ClusterForm(TenancyForm, ScopedForm, PrimaryModelForm):
type = DynamicModelChoiceField( type = DynamicModelChoiceField(
label=_('Type'), label=_('Type'),
queryset=ClusterType.objects.all(), queryset=ClusterType.objects.all(),
@@ -72,7 +66,6 @@ class ClusterForm(TenancyForm, ScopedForm, NetBoxModelForm):
required=False, required=False,
quick_add=True quick_add=True
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'type', 'group', 'status', 'description', 'tags', name=_('Cluster')), FieldSet('name', 'type', 'group', 'status', 'description', 'tags', name=_('Cluster')),
@@ -173,7 +166,7 @@ class ClusterRemoveDevicesForm(ConfirmationForm):
) )
class VirtualMachineForm(TenancyForm, NetBoxModelForm): class VirtualMachineForm(TenancyForm, PrimaryModelForm):
site = DynamicModelChoiceField( site = DynamicModelChoiceField(
label=_('Site'), label=_('Site'),
queryset=Site.objects.all(), queryset=Site.objects.all(),
@@ -221,7 +214,6 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
required=False, required=False,
label=_('Config template') label=_('Config template')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'role', 'status', 'description', 'serial', 'tags', name=_('Virtual Machine')), FieldSet('name', 'role', 'status', 'description', 'serial', 'tags', name=_('Virtual Machine')),

View File

@@ -4,9 +4,9 @@ from django.utils.translation import gettext_lazy as _
from dcim.models import Device, Interface from dcim.models import Device, Interface
from ipam.models import IPAddress, RouteTarget, VLAN from ipam.models import IPAddress, RouteTarget, VLAN
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField
from utilities.forms.rendering import FieldSet, TabbedGroups from utilities.forms.rendering import FieldSet, TabbedGroups
from utilities.forms.utils import add_blank_choice, get_field_value from utilities.forms.utils import add_blank_choice, get_field_value
from utilities.forms.widgets import HTMXSelect from utilities.forms.widgets import HTMXSelect
@@ -29,9 +29,7 @@ __all__ = (
) )
class TunnelGroupForm(NetBoxModelForm): class TunnelGroupForm(OrganizationalModelForm):
slug = SlugField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Tunnel Group')), FieldSet('name', 'slug', 'description', 'tags', name=_('Tunnel Group')),
) )
@@ -43,7 +41,7 @@ class TunnelGroupForm(NetBoxModelForm):
] ]
class TunnelForm(TenancyForm, NetBoxModelForm): class TunnelForm(TenancyForm, PrimaryModelForm):
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
queryset=TunnelGroup.objects.all(), queryset=TunnelGroup.objects.all(),
label=_('Tunnel Group'), label=_('Tunnel Group'),
@@ -55,7 +53,6 @@ class TunnelForm(TenancyForm, NetBoxModelForm):
label=_('IPSec Profile'), label=_('IPSec Profile'),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'status', 'group', 'encapsulation', 'description', 'tunnel_id', 'tags', name=_('Tunnel')), FieldSet('name', 'status', 'group', 'encapsulation', 'description', 'tunnel_id', 'tags', name=_('Tunnel')),
@@ -293,7 +290,7 @@ class TunnelTerminationForm(NetBoxModelForm):
self.instance.termination = self.cleaned_data.get('termination') self.instance.termination = self.cleaned_data.get('termination')
class IKEProposalForm(NetBoxModelForm): class IKEProposalForm(PrimaryModelForm):
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Proposal')), FieldSet('name', 'description', 'tags', name=_('Proposal')),
@@ -311,7 +308,7 @@ class IKEProposalForm(NetBoxModelForm):
] ]
class IKEPolicyForm(NetBoxModelForm): class IKEPolicyForm(PrimaryModelForm):
proposals = DynamicModelMultipleChoiceField( proposals = DynamicModelMultipleChoiceField(
queryset=IKEProposal.objects.all(), queryset=IKEProposal.objects.all(),
label=_('Proposals'), label=_('Proposals'),
@@ -330,7 +327,7 @@ class IKEPolicyForm(NetBoxModelForm):
] ]
class IPSecProposalForm(NetBoxModelForm): class IPSecProposalForm(PrimaryModelForm):
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Proposal')), FieldSet('name', 'description', 'tags', name=_('Proposal')),
@@ -348,7 +345,7 @@ class IPSecProposalForm(NetBoxModelForm):
] ]
class IPSecPolicyForm(NetBoxModelForm): class IPSecPolicyForm(PrimaryModelForm):
proposals = DynamicModelMultipleChoiceField( proposals = DynamicModelMultipleChoiceField(
queryset=IPSecProposal.objects.all(), queryset=IPSecProposal.objects.all(),
label=_('Proposals'), label=_('Proposals'),
@@ -367,7 +364,7 @@ class IPSecPolicyForm(NetBoxModelForm):
] ]
class IPSecProfileForm(NetBoxModelForm): class IPSecProfileForm(PrimaryModelForm):
ike_policy = DynamicModelChoiceField( ike_policy = DynamicModelChoiceField(
queryset=IKEPolicy.objects.all(), queryset=IKEPolicy.objects.all(),
label=_('IKE policy') label=_('IKE policy')
@@ -376,7 +373,6 @@ class IPSecProfileForm(NetBoxModelForm):
queryset=IPSecPolicy.objects.all(), queryset=IPSecPolicy.objects.all(),
label=_('IPSec policy') label=_('IPSec policy')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Profile')), FieldSet('name', 'description', 'tags', name=_('Profile')),
@@ -394,7 +390,7 @@ class IPSecProfileForm(NetBoxModelForm):
# L2VPN # L2VPN
# #
class L2VPNForm(TenancyForm, NetBoxModelForm): class L2VPNForm(TenancyForm, PrimaryModelForm):
slug = SlugField() slug = SlugField()
import_targets = DynamicModelMultipleChoiceField( import_targets = DynamicModelMultipleChoiceField(
label=_('Import targets'), label=_('Import targets'),
@@ -406,7 +402,6 @@ class L2VPNForm(TenancyForm, NetBoxModelForm):
queryset=RouteTarget.objects.all(), queryset=RouteTarget.objects.all(),
required=False required=False
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'type', 'status', 'identifier', 'description', 'tags', name=_('L2VPN')), FieldSet('name', 'slug', 'type', 'status', 'identifier', 'description', 'tags', name=_('L2VPN')),

View File

@@ -1,12 +1,12 @@
from django.forms import PasswordInput from django.forms import PasswordInput
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from dcim.models import Device, Interface, Location, Site
from dcim.forms.mixins import ScopedForm from dcim.forms.mixins import ScopedForm
from dcim.models import Device, Interface, Location, Site
from ipam.models import VLAN from ipam.models import VLAN
from netbox.forms import NetBoxModelForm from netbox.forms import NestedGroupModelForm, PrimaryModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField from utilities.forms.fields import DynamicModelChoiceField
from utilities.forms.mixins import DistanceValidationMixin from utilities.forms.mixins import DistanceValidationMixin
from utilities.forms.rendering import FieldSet, InlineFields from utilities.forms.rendering import FieldSet, InlineFields
from wireless.models import * from wireless.models import *
@@ -18,14 +18,12 @@ __all__ = (
) )
class WirelessLANGroupForm(NetBoxModelForm): class WirelessLANGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField( parent = DynamicModelChoiceField(
label=_('Parent'), label=_('Parent'),
queryset=WirelessLANGroup.objects.all(), queryset=WirelessLANGroup.objects.all(),
required=False required=False
) )
slug = SlugField()
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Wireless LAN Group')), FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Wireless LAN Group')),
@@ -38,7 +36,7 @@ class WirelessLANGroupForm(NetBoxModelForm):
] ]
class WirelessLANForm(ScopedForm, TenancyForm, NetBoxModelForm): class WirelessLANForm(ScopedForm, TenancyForm, PrimaryModelForm):
group = DynamicModelChoiceField( group = DynamicModelChoiceField(
label=_('Group'), label=_('Group'),
queryset=WirelessLANGroup.objects.all(), queryset=WirelessLANGroup.objects.all(),
@@ -51,7 +49,6 @@ class WirelessLANForm(ScopedForm, TenancyForm, NetBoxModelForm):
selector=True, selector=True,
label=_('VLAN') label=_('VLAN')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('ssid', 'group', 'vlan', 'status', 'description', 'tags', name=_('Wireless LAN')), FieldSet('ssid', 'group', 'vlan', 'status', 'description', 'tags', name=_('Wireless LAN')),
@@ -74,7 +71,7 @@ class WirelessLANForm(ScopedForm, TenancyForm, NetBoxModelForm):
} }
class WirelessLinkForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm): class WirelessLinkForm(DistanceValidationMixin, TenancyForm, PrimaryModelForm):
site_a = DynamicModelChoiceField( site_a = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
@@ -159,7 +156,6 @@ class WirelessLinkForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
}, },
label=_('Interface') label=_('Interface')
) )
comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('site_a', 'location_a', 'device_a', 'interface_a', name=_('Side A')), FieldSet('site_a', 'location_a', 'device_a', 'interface_a', name=_('Side A')),