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

View File

@@ -9,11 +9,11 @@ from django.utils.translation import gettext_lazy as _
from core.forms.mixins import SyncedDataMixin
from core.models import *
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.utils import get_data_backend_choices
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.widgets import HTMXSelect
@@ -26,12 +26,11 @@ __all__ = (
EMPTY_VALUES = ('', None, [], ())
class DataSourceForm(NetBoxModelForm):
class DataSourceForm(PrimaryModelForm):
type = forms.ChoiceField(
choices=get_data_backend_choices,
widget=HTMXSelect()
)
comments = CommentField()
class Meta:
model = DataSource

View File

@@ -10,13 +10,13 @@ from dcim.models import *
from extras.models import ConfigTemplate
from ipam.choices import VLANQinQRoleChoices
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 tenancy.forms import TenancyForm
from users.models import User
from utilities.forms import add_blank_choice, get_field_value
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.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK
@@ -75,14 +75,12 @@ __all__ = (
)
class RegionForm(NetBoxModelForm):
class RegionForm(NestedGroupModelForm):
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=Region.objects.all(),
required=False
)
slug = SlugField()
comments = CommentField()
fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags'),
@@ -95,14 +93,12 @@ class RegionForm(NetBoxModelForm):
)
class SiteGroupForm(NetBoxModelForm):
class SiteGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=SiteGroup.objects.all(),
required=False
)
slug = SlugField()
comments = CommentField()
fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags'),
@@ -115,7 +111,7 @@ class SiteGroupForm(NetBoxModelForm):
)
class SiteForm(TenancyForm, NetBoxModelForm):
class SiteForm(TenancyForm, PrimaryModelForm):
region = DynamicModelChoiceField(
label=_('Region'),
queryset=Region.objects.all(),
@@ -139,7 +135,6 @@ class SiteForm(TenancyForm, NetBoxModelForm):
choices=add_blank_choice(TimeZoneFormField().choices),
required=False
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -170,7 +165,7 @@ class SiteForm(TenancyForm, NetBoxModelForm):
}
class LocationForm(TenancyForm, NetBoxModelForm):
class LocationForm(TenancyForm, NestedGroupModelForm):
site = DynamicModelChoiceField(
label=_('Site'),
queryset=Site.objects.all(),
@@ -184,8 +179,6 @@ class LocationForm(TenancyForm, NetBoxModelForm):
'site_id': '$site'
}
)
slug = SlugField()
comments = CommentField()
fieldsets = (
FieldSet('site', 'parent', 'name', 'slug', 'status', 'facility', 'description', 'tags', name=_('Location')),
@@ -200,9 +193,7 @@ class LocationForm(TenancyForm, NetBoxModelForm):
)
class RackRoleForm(NetBoxModelForm):
slug = SlugField()
class RackRoleForm(OrganizationalModelForm):
fieldsets = (
FieldSet('name', 'slug', 'color', 'description', 'tags', name=_('Rack Role')),
)
@@ -214,13 +205,12 @@ class RackRoleForm(NetBoxModelForm):
]
class RackTypeForm(NetBoxModelForm):
class RackTypeForm(PrimaryModelForm):
manufacturer = DynamicModelChoiceField(
label=_('Manufacturer'),
queryset=Manufacturer.objects.all(),
quick_add=True
)
comments = CommentField()
slug = SlugField(
label=_('Slug'),
slug_source='model'
@@ -246,7 +236,7 @@ class RackTypeForm(NetBoxModelForm):
]
class RackForm(TenancyForm, NetBoxModelForm):
class RackForm(TenancyForm, PrimaryModelForm):
site = DynamicModelChoiceField(
label=_('Site'),
queryset=Site.objects.all(),
@@ -271,7 +261,6 @@ class RackForm(TenancyForm, NetBoxModelForm):
required=False,
help_text=_("Select a pre-defined rack type, or set physical characteristics below.")
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -333,7 +322,6 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
label=_('User'),
queryset=User.objects.order_by('username')
)
comments = CommentField()
fieldsets = (
FieldSet('rack', 'units', 'status', 'user', 'description', 'tags', name=_('Reservation')),
@@ -347,9 +335,7 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
]
class ManufacturerForm(NetBoxModelForm):
slug = SlugField()
class ManufacturerForm(OrganizationalModelForm):
fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Manufacturer')),
)
@@ -361,7 +347,7 @@ class ManufacturerForm(NetBoxModelForm):
]
class DeviceTypeForm(NetBoxModelForm):
class DeviceTypeForm(PrimaryModelForm):
manufacturer = DynamicModelChoiceField(
label=_('Manufacturer'),
queryset=Manufacturer.objects.all(),
@@ -380,7 +366,6 @@ class DeviceTypeForm(NetBoxModelForm):
label=_('Slug'),
slug_source='model'
)
comments = CommentField()
fieldsets = (
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(
label=_('Schema'),
required=False,
help_text=_("Enter a valid JSON schema to define supported attributes.")
)
comments = CommentField()
fieldsets = (
FieldSet('name', 'description', 'schema', 'tags', name=_('Profile')),
@@ -427,7 +411,7 @@ class ModuleTypeProfileForm(NetBoxModelForm):
]
class ModuleTypeForm(NetBoxModelForm):
class ModuleTypeForm(PrimaryModelForm):
profile = forms.ModelChoiceField(
queryset=ModuleTypeProfile.objects.all(),
label=_('Profile'),
@@ -438,7 +422,6 @@ class ModuleTypeForm(NetBoxModelForm):
label=_('Manufacturer'),
queryset=Manufacturer.objects.all()
)
comments = CommentField()
@property
def fieldsets(self):
@@ -507,19 +490,17 @@ class ModuleTypeForm(NetBoxModelForm):
return super()._post_clean()
class DeviceRoleForm(NetBoxModelForm):
class DeviceRoleForm(NestedGroupModelForm):
config_template = DynamicModelChoiceField(
label=_('Config template'),
queryset=ConfigTemplate.objects.all(),
required=False
)
slug = SlugField()
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=DeviceRole.objects.all(),
required=False,
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -535,7 +516,7 @@ class DeviceRoleForm(NetBoxModelForm):
]
class PlatformForm(NetBoxModelForm):
class PlatformForm(NestedGroupModelForm):
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=Platform.objects.all(),
@@ -556,7 +537,6 @@ class PlatformForm(NetBoxModelForm):
label=_('Slug'),
max_length=64
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -571,7 +551,7 @@ class PlatformForm(NetBoxModelForm):
]
class DeviceForm(TenancyForm, NetBoxModelForm):
class DeviceForm(TenancyForm, PrimaryModelForm):
site = DynamicModelChoiceField(
label=_('Site'),
queryset=Site.objects.all(),
@@ -641,7 +621,6 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
'site_id': ['$site', 'null']
},
)
comments = CommentField()
local_context_data = JSONField(
required=False,
label=''
@@ -742,7 +721,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
self.fields['position'].widget.choices = [(position, f'U{position}')]
class ModuleForm(ModuleCommonForm, NetBoxModelForm):
class ModuleForm(ModuleCommonForm, PrimaryModelForm):
device = DynamicModelChoiceField(
label=_('Device'),
queryset=Device.objects.all(),
@@ -765,7 +744,6 @@ class ModuleForm(ModuleCommonForm, NetBoxModelForm):
},
selector=True
)
comments = CommentField()
replicate_components = forms.BooleanField(
label=_('Replicate components'),
required=False,
@@ -809,7 +787,7 @@ def get_termination_type_choices():
])
class CableForm(TenancyForm, NetBoxModelForm):
class CableForm(TenancyForm, PrimaryModelForm):
a_terminations_type = forms.ChoiceField(
choices=get_termination_type_choices,
required=False,
@@ -822,7 +800,6 @@ class CableForm(TenancyForm, NetBoxModelForm):
widget=HTMXSelect(),
label=_('Type')
)
comments = CommentField()
class Meta:
model = Cable
@@ -832,7 +809,7 @@ class CableForm(TenancyForm, NetBoxModelForm):
]
class PowerPanelForm(NetBoxModelForm):
class PowerPanelForm(PrimaryModelForm):
site = DynamicModelChoiceField(
label=_('Site'),
queryset=Site.objects.all(),
@@ -846,7 +823,6 @@ class PowerPanelForm(NetBoxModelForm):
'site_id': '$site'
}
)
comments = CommentField()
fieldsets = (
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(
label=_('Power panel'),
queryset=PowerPanel.objects.all(),
@@ -872,7 +848,6 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
required=False,
selector=True
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -895,13 +870,12 @@ class PowerFeedForm(TenancyForm, NetBoxModelForm):
# Virtual chassis
#
class VirtualChassisForm(NetBoxModelForm):
class VirtualChassisForm(PrimaryModelForm):
master = forms.ModelChoiceField(
label=_('Master'),
queryset=Device.objects.all(),
required=False,
)
comments = CommentField()
class Meta:
model = VirtualChassis
@@ -1829,9 +1803,7 @@ class InventoryItemForm(DeviceComponentForm):
self.instance.component = None
class InventoryItemRoleForm(NetBoxModelForm):
slug = SlugField()
class InventoryItemRoleForm(OrganizationalModelForm):
fieldsets = (
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(
label=_('Device'),
queryset=Device.objects.all(),
@@ -1888,7 +1860,7 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
# Addressing
#
class MACAddressForm(NetBoxModelForm):
class MACAddressForm(PrimaryModelForm):
mac_address = forms.CharField(
required=True,
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.models import *
from netbox.events import get_event_type_choices
from netbox.forms import NetBoxModelForm
from netbox.forms.mixins import ChangelogMessageMixin
from netbox.forms import NetBoxModelForm, PrimaryModelForm
from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
from tenancy.models import Tenant, TenantGroup
from users.models import Group, User
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(
label=_('Object types'),
queryset=ObjectType.objects.with_feature('custom_fields'),
@@ -166,7 +166,7 @@ class CustomFieldForm(ChangelogMessageMixin, forms.ModelForm):
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
extra_choices = forms.CharField(
widget=ChoicesWidget(),
@@ -219,7 +219,7 @@ class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
return data
class CustomLinkForm(ChangelogMessageMixin, forms.ModelForm):
class CustomLinkForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField(
label=_('Object types'),
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(
label=_('Object types'),
queryset=ObjectType.objects.with_feature('export_templates')
@@ -293,7 +293,7 @@ class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm
return self.cleaned_data
class SavedFilterForm(ChangelogMessageMixin, forms.ModelForm):
class SavedFilterForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
slug = SlugField()
object_types = ContentTypeMultipleChoiceField(
label=_('Object types'),
@@ -427,7 +427,7 @@ class SubscriptionForm(forms.ModelForm):
fields = ('object_type', 'object_id')
class WebhookForm(NetBoxModelForm):
class WebhookForm(OwnerMixin, NetBoxModelForm):
fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Webhook')),
@@ -447,7 +447,7 @@ class WebhookForm(NetBoxModelForm):
}
class EventRuleForm(NetBoxModelForm):
class EventRuleForm(OwnerMixin, NetBoxModelForm):
object_types = ContentTypeMultipleChoiceField(
label=_('Object types'),
queryset=ObjectType.objects.with_feature('event_rules'),
@@ -563,7 +563,7 @@ class EventRuleForm(NetBoxModelForm):
return self.cleaned_data
class TagForm(ChangelogMessageMixin, forms.ModelForm):
class TagForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
slug = SlugField()
object_types = ContentTypeMultipleChoiceField(
label=_('Object types'),
@@ -586,7 +586,7 @@ class TagForm(ChangelogMessageMixin, forms.ModelForm):
]
class ConfigContextProfileForm(SyncedDataMixin, NetBoxModelForm):
class ConfigContextProfileForm(SyncedDataMixin, PrimaryModelForm):
schema = JSONField(
label=_('Schema'),
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(
label=_('Profile'),
queryset=ConfigContextProfile.objects.all(),
@@ -728,7 +728,7 @@ class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm)
return self.cleaned_data
class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, OwnerMixin, forms.ModelForm):
tags = DynamicModelMultipleChoiceField(
label=_('Tags'),
queryset=Tag.objects.all(),

View File

@@ -9,13 +9,13 @@ from ipam.choices import *
from ipam.constants import *
from ipam.formfields import IPNetworkFormField
from ipam.models import *
from netbox.forms import NetBoxModelForm
from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
from tenancy.forms import TenancyForm
from utilities.exceptions import PermissionsViolation
from utilities.forms import add_blank_choice
from utilities.forms.fields import (
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
NumericRangeArrayField, SlugField
ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
NumericRangeArrayField,
)
from utilities.forms.rendering import FieldSet, InlineFields, ObjectAttribute, TabbedGroups
from utilities.forms.utils import get_field_value
@@ -49,7 +49,7 @@ __all__ = (
)
class VRFForm(TenancyForm, NetBoxModelForm):
class VRFForm(TenancyForm, PrimaryModelForm):
import_targets = DynamicModelMultipleChoiceField(
label=_('Import targets'),
queryset=RouteTarget.objects.all(),
@@ -60,7 +60,6 @@ class VRFForm(TenancyForm, NetBoxModelForm):
queryset=RouteTarget.objects.all(),
required=False
)
comments = CommentField()
fieldsets = (
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 = (
FieldSet('name', 'description', 'tags', name=_('Route Target')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
)
comments = CommentField()
class Meta:
model = RouteTarget
@@ -93,9 +91,7 @@ class RouteTargetForm(TenancyForm, NetBoxModelForm):
]
class RIRForm(NetBoxModelForm):
slug = SlugField()
class RIRForm(OrganizationalModelForm):
fieldsets = (
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(
queryset=RIR.objects.all(),
label=_('RIR'),
quick_add=True
)
comments = CommentField()
fieldsets = (
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(
queryset=RIR.objects.all(),
label=_('RIR'),
quick_add=True
)
slug = SlugField()
fieldsets = (
FieldSet('name', 'slug', 'rir', 'start', 'end', 'description', 'tags', name=_('ASN Range')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
@@ -149,7 +143,7 @@ class ASNRangeForm(TenancyForm, NetBoxModelForm):
]
class ASNForm(TenancyForm, NetBoxModelForm):
class ASNForm(TenancyForm, PrimaryModelForm):
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
label=_('RIR'),
@@ -160,7 +154,6 @@ class ASNForm(TenancyForm, NetBoxModelForm):
label=_('Sites'),
required=False
)
comments = CommentField()
fieldsets = (
FieldSet('asn', 'rir', 'sites', 'description', 'tags', name=_('ASN')),
@@ -188,9 +181,7 @@ class ASNForm(TenancyForm, NetBoxModelForm):
return instance
class RoleForm(NetBoxModelForm):
slug = SlugField()
class RoleForm(OrganizationalModelForm):
fieldsets = (
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(
queryset=VRF.objects.all(),
required=False,
@@ -223,7 +214,6 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
required=False,
quick_add=True
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -250,7 +240,7 @@ class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm):
self.fields['vlan'].widget.attrs.pop('data-dynamic-params', None)
class IPRangeForm(TenancyForm, NetBoxModelForm):
class IPRangeForm(TenancyForm, PrimaryModelForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
@@ -262,7 +252,6 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
required=False,
quick_add=True
)
comments = CommentField()
fieldsets = (
FieldSet(
@@ -280,7 +269,7 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
]
class IPAddressForm(TenancyForm, NetBoxModelForm):
class IPAddressForm(TenancyForm, PrimaryModelForm):
interface = DynamicModelChoiceField(
queryset=Interface.objects.all(),
required=False,
@@ -324,7 +313,6 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
required=False,
label=_('Make this the out-of-band IP for the device')
)
comments = CommentField()
fieldsets = (
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
ip_vrf = DynamicModelChoiceField(
@@ -511,7 +499,6 @@ class FHRPGroupForm(NetBoxModelForm):
required=False,
label=_('Status')
)
comments = CommentField()
fieldsets = (
FieldSet('protocol', 'group_id', 'name', 'description', 'tags', name=_('FHRP Group')),
@@ -599,8 +586,7 @@ class FHRPGroupAssignmentForm(forms.ModelForm):
return group
class VLANGroupForm(TenancyForm, NetBoxModelForm):
slug = SlugField()
class VLANGroupForm(TenancyForm, OrganizationalModelForm):
vid_ranges = NumericRangeArrayField(
label=_('VLAN IDs')
)
@@ -662,7 +648,7 @@ class VLANGroupForm(TenancyForm, NetBoxModelForm):
self.instance.scope = self.cleaned_data.get('scope')
class VLANForm(TenancyForm, NetBoxModelForm):
class VLANForm(TenancyForm, PrimaryModelForm):
group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
@@ -698,7 +684,6 @@ class VLANForm(TenancyForm, NetBoxModelForm):
'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE,
}
)
comments = CommentField()
class Meta:
model = VLAN
@@ -708,7 +693,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
]
class VLANTranslationPolicyForm(NetBoxModelForm):
class VLANTranslationPolicyForm(PrimaryModelForm):
fieldsets = (
FieldSet('name', 'description', 'tags', name=_('VLAN Translation Policy')),
@@ -739,7 +724,7 @@ class VLANTranslationRuleForm(NetBoxModelForm):
]
class ServiceTemplateForm(NetBoxModelForm):
class ServiceTemplateForm(PrimaryModelForm):
ports = NumericArrayField(
label=_('Ports'),
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.")
)
comments = CommentField()
fieldsets = (
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')
class ServiceForm(NetBoxModelForm):
class ServiceForm(PrimaryModelForm):
parent_object_type = ContentTypeChoiceField(
queryset=ContentType.objects.filter(SERVICE_ASSIGNMENT_MODELS),
widget=HTMXSelect(),
@@ -786,7 +770,6 @@ class ServiceForm(NetBoxModelForm):
required=False,
label=_('IP Addresses'),
)
comments = CommentField()
fieldsets = (
FieldSet(

View File

@@ -4,11 +4,15 @@ from django import forms
from django.contrib.contenttypes.models import ContentType
from extras.choices import *
from utilities.forms.fields import CommentField, SlugField
from utilities.forms.mixins import CheckLastUpdatedMixin
from .mixins import ChangelogMessageMixin, CustomFieldsMixin, OwnerMixin, TagsMixin
__all__ = (
'NestedGroupModelForm',
'NetBoxModelForm',
'OrganizationalModelForm',
'PrimaryModelForm',
)
@@ -16,7 +20,6 @@ class NetBoxModelForm(
ChangelogMessageMixin,
CheckLastUpdatedMixin,
CustomFieldsMixin,
OwnerMixin,
TagsMixin,
forms.ModelForm
):
@@ -74,3 +77,25 @@ class NetBoxModelForm(
self.instance._m2m_values[field.name] = list(self.cleaned_data[field.name])
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.utils.translation import gettext_lazy as _
from netbox.forms import NetBoxModelForm
from netbox.forms import NestedGroupModelForm, NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
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
__all__ = (
@@ -20,14 +20,12 @@ __all__ = (
# Tenants
#
class TenantGroupForm(NetBoxModelForm):
class TenantGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=TenantGroup.objects.all(),
required=False
)
slug = SlugField()
comments = CommentField()
fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Tenant Group')),
@@ -40,14 +38,13 @@ class TenantGroupForm(NetBoxModelForm):
]
class TenantForm(NetBoxModelForm):
class TenantForm(PrimaryModelForm):
slug = SlugField()
group = DynamicModelChoiceField(
label=_('Group'),
queryset=TenantGroup.objects.all(),
required=False
)
comments = CommentField()
fieldsets = (
FieldSet('name', 'slug', 'group', 'description', 'tags', name=_('Tenant')),
@@ -64,14 +61,12 @@ class TenantForm(NetBoxModelForm):
# Contacts
#
class ContactGroupForm(NetBoxModelForm):
class ContactGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=ContactGroup.objects.all(),
required=False
)
slug = SlugField()
comments = CommentField()
fieldsets = (
FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Contact Group')),
@@ -82,9 +77,7 @@ class ContactGroupForm(NetBoxModelForm):
fields = ('parent', 'name', 'slug', 'description', 'owner', 'comments', 'tags')
class ContactRoleForm(NetBoxModelForm):
slug = SlugField()
class ContactRoleForm(OrganizationalModelForm):
fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Contact Role')),
)
@@ -94,7 +87,7 @@ class ContactRoleForm(NetBoxModelForm):
fields = ('name', 'slug', 'description', 'owner', 'tags')
class ContactForm(NetBoxModelForm):
class ContactForm(PrimaryModelForm):
groups = DynamicModelMultipleChoiceField(
label=_('Groups'),
queryset=ContactGroup.objects.all(),
@@ -105,7 +98,6 @@ class ContactForm(NetBoxModelForm):
assume_scheme='https',
required=False,
)
comments = CommentField()
fieldsets = (
FieldSet(

View File

@@ -10,12 +10,10 @@ from dcim.models import Device, DeviceRole, MACAddress, Platform, Rack, Region,
from extras.models import ConfigTemplate
from ipam.choices import VLANQinQRoleChoices
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 utilities.forms import ConfirmationForm
from utilities.forms.fields import (
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, SlugField,
)
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField
from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import HTMXSelect
from virtualization.models import *
@@ -32,9 +30,7 @@ __all__ = (
)
class ClusterTypeForm(NetBoxModelForm):
slug = SlugField()
class ClusterTypeForm(OrganizationalModelForm):
fieldsets = (
FieldSet('name', 'slug', 'description', 'tags', name=_('Cluster Type')),
)
@@ -46,9 +42,7 @@ class ClusterTypeForm(NetBoxModelForm):
)
class ClusterGroupForm(NetBoxModelForm):
slug = SlugField()
class ClusterGroupForm(OrganizationalModelForm):
fieldsets = (
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(
label=_('Type'),
queryset=ClusterType.objects.all(),
@@ -72,7 +66,6 @@ class ClusterForm(TenancyForm, ScopedForm, NetBoxModelForm):
required=False,
quick_add=True
)
comments = CommentField()
fieldsets = (
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(
label=_('Site'),
queryset=Site.objects.all(),
@@ -221,7 +214,6 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
required=False,
label=_('Config template')
)
comments = CommentField()
fieldsets = (
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 ipam.models import IPAddress, RouteTarget, VLAN
from netbox.forms import NetBoxModelForm
from netbox.forms import NetBoxModelForm, OrganizationalModelForm, PrimaryModelForm
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.utils import add_blank_choice, get_field_value
from utilities.forms.widgets import HTMXSelect
@@ -29,9 +29,7 @@ __all__ = (
)
class TunnelGroupForm(NetBoxModelForm):
slug = SlugField()
class TunnelGroupForm(OrganizationalModelForm):
fieldsets = (
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(
queryset=TunnelGroup.objects.all(),
label=_('Tunnel Group'),
@@ -55,7 +53,6 @@ class TunnelForm(TenancyForm, NetBoxModelForm):
label=_('IPSec Profile'),
required=False
)
comments = CommentField()
fieldsets = (
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')
class IKEProposalForm(NetBoxModelForm):
class IKEProposalForm(PrimaryModelForm):
fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Proposal')),
@@ -311,7 +308,7 @@ class IKEProposalForm(NetBoxModelForm):
]
class IKEPolicyForm(NetBoxModelForm):
class IKEPolicyForm(PrimaryModelForm):
proposals = DynamicModelMultipleChoiceField(
queryset=IKEProposal.objects.all(),
label=_('Proposals'),
@@ -330,7 +327,7 @@ class IKEPolicyForm(NetBoxModelForm):
]
class IPSecProposalForm(NetBoxModelForm):
class IPSecProposalForm(PrimaryModelForm):
fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Proposal')),
@@ -348,7 +345,7 @@ class IPSecProposalForm(NetBoxModelForm):
]
class IPSecPolicyForm(NetBoxModelForm):
class IPSecPolicyForm(PrimaryModelForm):
proposals = DynamicModelMultipleChoiceField(
queryset=IPSecProposal.objects.all(),
label=_('Proposals'),
@@ -367,7 +364,7 @@ class IPSecPolicyForm(NetBoxModelForm):
]
class IPSecProfileForm(NetBoxModelForm):
class IPSecProfileForm(PrimaryModelForm):
ike_policy = DynamicModelChoiceField(
queryset=IKEPolicy.objects.all(),
label=_('IKE policy')
@@ -376,7 +373,6 @@ class IPSecProfileForm(NetBoxModelForm):
queryset=IPSecPolicy.objects.all(),
label=_('IPSec policy')
)
comments = CommentField()
fieldsets = (
FieldSet('name', 'description', 'tags', name=_('Profile')),
@@ -394,7 +390,7 @@ class IPSecProfileForm(NetBoxModelForm):
# L2VPN
#
class L2VPNForm(TenancyForm, NetBoxModelForm):
class L2VPNForm(TenancyForm, PrimaryModelForm):
slug = SlugField()
import_targets = DynamicModelMultipleChoiceField(
label=_('Import targets'),
@@ -406,7 +402,6 @@ class L2VPNForm(TenancyForm, NetBoxModelForm):
queryset=RouteTarget.objects.all(),
required=False
)
comments = CommentField()
fieldsets = (
FieldSet('name', 'slug', 'type', 'status', 'identifier', 'description', 'tags', name=_('L2VPN')),

View File

@@ -1,12 +1,12 @@
from django.forms import PasswordInput
from django.utils.translation import gettext_lazy as _
from dcim.models import Device, Interface, Location, Site
from dcim.forms.mixins import ScopedForm
from dcim.models import Device, Interface, Location, Site
from ipam.models import VLAN
from netbox.forms import NetBoxModelForm
from netbox.forms import NestedGroupModelForm, PrimaryModelForm
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.rendering import FieldSet, InlineFields
from wireless.models import *
@@ -18,14 +18,12 @@ __all__ = (
)
class WirelessLANGroupForm(NetBoxModelForm):
class WirelessLANGroupForm(NestedGroupModelForm):
parent = DynamicModelChoiceField(
label=_('Parent'),
queryset=WirelessLANGroup.objects.all(),
required=False
)
slug = SlugField()
comments = CommentField()
fieldsets = (
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(
label=_('Group'),
queryset=WirelessLANGroup.objects.all(),
@@ -51,7 +49,6 @@ class WirelessLANForm(ScopedForm, TenancyForm, NetBoxModelForm):
selector=True,
label=_('VLAN')
)
comments = CommentField()
fieldsets = (
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(
queryset=Site.objects.all(),
required=False,
@@ -159,7 +156,6 @@ class WirelessLinkForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
},
label=_('Interface')
)
comments = CommentField()
fieldsets = (
FieldSet('site_a', 'location_a', 'device_a', 'interface_a', name=_('Side A')),