1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Added tenant_group/tenant form section to all objects with tenancy

This commit is contained in:
Jeremy Stretch
2017-05-11 17:35:20 -04:00
parent 45bb7eec0b
commit 473b35f9a3
12 changed files with 133 additions and 35 deletions

View File

@ -3,6 +3,7 @@ from django.db.models import Count
from dcim.models import Site, Device, Interface, Rack, VIRTUAL_IFACE_TYPES from dcim.models import Site, Device, Interface, Rack, VIRTUAL_IFACE_TYPES
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from tenancy.forms import TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, BootstrapMixin, BulkImportForm, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, CSVDataField, APISelect, BootstrapMixin, BulkImportForm, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, CSVDataField,
@ -83,12 +84,15 @@ class CircuitTypeForm(BootstrapMixin, forms.ModelForm):
# Circuits # Circuits
# #
class CircuitForm(BootstrapMixin, CustomFieldForm): class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
comments = CommentField() comments = CommentField()
class Meta: class Meta:
model = Circuit model = Circuit
fields = ['cid', 'type', 'provider', 'tenant', 'install_date', 'commit_rate', 'description', 'comments'] fields = [
'cid', 'type', 'provider', 'install_date', 'commit_rate', 'description', 'tenant_group', 'tenant',
'comments',
]
help_texts = { help_texts = {
'cid': "Unique circuit ID", 'cid': "Unique circuit ID",
'install_date': "Format: YYYY-MM-DD", 'install_date': "Format: YYYY-MM-DD",

View File

@ -8,6 +8,7 @@ from django.db.models import Count, Q
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from ipam.models import IPAddress from ipam.models import IPAddress
from tenancy.forms import TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
@ -81,7 +82,7 @@ class RegionForm(BootstrapMixin, forms.ModelForm):
# Sites # Sites
# #
class SiteForm(BootstrapMixin, CustomFieldForm): class SiteForm(BootstrapMixin, TenancyForm, CustomFieldForm):
region = TreeNodeChoiceField(queryset=Region.objects.all(), required=False) region = TreeNodeChoiceField(queryset=Region.objects.all(), required=False)
slug = SlugField() slug = SlugField()
comments = CommentField() comments = CommentField()
@ -89,8 +90,8 @@ class SiteForm(BootstrapMixin, CustomFieldForm):
class Meta: class Meta:
model = Site model = Site
fields = [ fields = [
'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address', 'name', 'slug', 'region', 'tenant_group', 'tenant', 'facility', 'asn', 'physical_address',
'contact_name', 'contact_phone', 'contact_email', 'comments', 'shipping_address', 'contact_name', 'contact_phone', 'contact_email', 'comments',
] ]
widgets = { widgets = {
'physical_address': SmallTextarea(attrs={'rows': 3}), 'physical_address': SmallTextarea(attrs={'rows': 3}),
@ -185,7 +186,7 @@ class RackRoleForm(BootstrapMixin, forms.ModelForm):
# Racks # Racks
# #
class RackForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm): class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
group = ChainedModelChoiceField( group = ChainedModelChoiceField(
queryset=RackGroup.objects.all(), queryset=RackGroup.objects.all(),
chains={'site': 'site'}, chains={'site': 'site'},
@ -199,8 +200,8 @@ class RackForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm):
class Meta: class Meta:
model = Rack model = Rack
fields = [ fields = [
'site', 'group', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units', 'site', 'group', 'name', 'facility_id', 'tenant_group', 'tenant', 'role', 'type', 'width', 'u_height',
'comments', 'desc_units', 'comments',
] ]
help_texts = { help_texts = {
'site': "The site at which the rack exists", 'site': "The site at which the rack exists",
@ -534,7 +535,7 @@ class PlatformForm(BootstrapMixin, forms.ModelForm):
# Devices # Devices
# #
class DeviceForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm): class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldForm):
site = forms.ModelChoiceField( site = forms.ModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
widget=forms.Select( widget=forms.Select(
@ -580,8 +581,8 @@ class DeviceForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm):
class Meta: class Meta:
model = Device model = Device
fields = [ fields = [
'name', 'device_role', 'tenant', 'device_type', 'serial', 'asset_tag', 'site', 'rack', 'position', 'face', 'name', 'device_role', 'device_type', 'serial', 'asset_tag', 'site', 'rack', 'position', 'face', 'status',
'status', 'platform', 'primary_ip4', 'primary_ip6', 'comments', 'platform', 'primary_ip4', 'primary_ip6', 'tenant_group', 'tenant', 'comments',
] ]
help_texts = { help_texts = {
'device_role': "The function this device serves", 'device_role': "The function this device serves",

View File

@ -3,10 +3,11 @@ from django.db.models import Count
from dcim.models import Site, Rack, Device, Interface from dcim.models import Site, Rack, Device, Interface
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from tenancy.forms import TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, BootstrapMixin, BulkEditNullBooleanSelect, BulkImportForm, ChainedFieldsMixin, ChainedModelChoiceField, APISelect, BootstrapMixin, BulkEditNullBooleanSelect, BulkImportForm, ChainedModelChoiceField, CSVDataField,
CSVDataField, ExpandableIPAddressField, FilterChoiceField, Livesearch, ReturnURLForm, SlugField, add_blank_choice, ExpandableIPAddressField, FilterChoiceField, Livesearch, ReturnURLForm, SlugField, add_blank_choice,
) )
from .models import ( from .models import (
@ -32,11 +33,11 @@ IPADDRESS_MASK_LENGTH_CHOICES = PREFIX_MASK_LENGTH_CHOICES + [(128, 128)]
# VRFs # VRFs
# #
class VRFForm(BootstrapMixin, CustomFieldForm): class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
class Meta: class Meta:
model = VRF model = VRF
fields = ['name', 'rd', 'tenant', 'enforce_unique', 'description'] fields = ['name', 'rd', 'enforce_unique', 'description', 'tenant_group', 'tenant']
labels = { labels = {
'rd': "RD", 'rd': "RD",
} }
@ -163,7 +164,7 @@ class RoleForm(BootstrapMixin, forms.ModelForm):
# Prefixes # Prefixes
# #
class PrefixForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm): class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
site = forms.ModelChoiceField( site = forms.ModelChoiceField(
queryset=Site.objects.all(), required=False, label='Site', widget=forms.Select( queryset=Site.objects.all(), required=False, label='Site', widget=forms.Select(
attrs={'filter-for': 'vlan', 'nullable': 'true'} attrs={'filter-for': 'vlan', 'nullable': 'true'}
@ -177,7 +178,7 @@ class PrefixForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm):
class Meta: class Meta:
model = Prefix model = Prefix
fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan', 'status', 'role', 'is_pool', 'description'] fields = ['prefix', 'vrf', 'site', 'vlan', 'status', 'role', 'is_pool', 'description', 'tenant_group', 'tenant']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(PrefixForm, self).__init__(*args, **kwargs) super(PrefixForm, self).__init__(*args, **kwargs)
@ -306,7 +307,7 @@ class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
# IP addresses # IP addresses
# #
class IPAddressForm(BootstrapMixin, ChainedFieldsMixin, ReturnURLForm, CustomFieldForm): class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm):
interface_site = forms.ModelChoiceField( interface_site = forms.ModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
@ -399,7 +400,10 @@ class IPAddressForm(BootstrapMixin, ChainedFieldsMixin, ReturnURLForm, CustomFie
class Meta: class Meta:
model = IPAddress model = IPAddress
fields = ['address', 'vrf', 'tenant', 'status', 'description', 'interface', 'primary_for_device', 'nat_inside'] fields = [
'address', 'vrf', 'status', 'description', 'interface', 'primary_for_device', 'nat_inside', 'tenant_group',
'tenant',
]
def __init__(self, instance=None, initial=None, *args, **kwargs): def __init__(self, instance=None, initial=None, *args, **kwargs):
@ -600,7 +604,7 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
# VLANs # VLANs
# #
class VLANForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm): class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
site = forms.ModelChoiceField( site = forms.ModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
widget=forms.Select( widget=forms.Select(
@ -619,7 +623,7 @@ class VLANForm(BootstrapMixin, ChainedFieldsMixin, CustomFieldForm):
class Meta: class Meta:
model = VLAN model = VLAN
fields = ['site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description'] fields = ['site', 'group', 'vid', 'name', 'status', 'role', 'description', 'tenant_group', 'tenant']
help_texts = { help_texts = {
'site': "Leave blank if this VLAN spans multiple sites", 'site': "Leave blank if this VLAN spans multiple sites",
'group': "VLAN group (optional)", 'group': "VLAN group (optional)",

View File

@ -8,12 +8,18 @@
{% render_field form.provider %} {% render_field form.provider %}
{% render_field form.cid %} {% render_field form.cid %}
{% render_field form.type %} {% render_field form.type %}
{% render_field form.tenant %}
{% render_field form.install_date %} {% render_field form.install_date %}
{% render_field form.commit_rate %} {% render_field form.commit_rate %}
{% render_field form.description %} {% render_field form.description %}
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
{% if form.custom_fields %} {% if form.custom_fields %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><strong>Custom Fields</strong></div> <div class="panel-heading"><strong>Custom Fields</strong></div>

View File

@ -7,7 +7,6 @@
<div class="panel-body"> <div class="panel-body">
{% render_field form.name %} {% render_field form.name %}
{% render_field form.device_role %} {% render_field form.device_role %}
{% render_field form.tenant %}
</div> </div>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
@ -63,6 +62,13 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
{% if form.custom_fields %} {% if form.custom_fields %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><strong>Custom Fields</strong></div> <div class="panel-heading"><strong>Custom Fields</strong></div>

View File

@ -6,11 +6,22 @@
<div class="panel-heading"><strong>Rack</strong></div> <div class="panel-heading"><strong>Rack</strong></div>
<div class="panel-body"> <div class="panel-body">
{% render_field form.site %} {% render_field form.site %}
{% render_field form.group %}
{% render_field form.name %} {% render_field form.name %}
{% render_field form.facility_id %} {% render_field form.facility_id %}
{% render_field form.tenant %} {% render_field form.group %}
{% render_field form.role %} {% render_field form.role %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Dimensions</strong></div>
<div class="panel-body">
{% render_field form.type %} {% render_field form.type %}
{% render_field form.width %} {% render_field form.width %}
{% render_field form.u_height %} {% render_field form.u_height %}

View File

@ -8,11 +8,17 @@
{% render_field form.name %} {% render_field form.name %}
{% render_field form.slug %} {% render_field form.slug %}
{% render_field form.region %} {% render_field form.region %}
{% render_field form.tenant %}
{% render_field form.facility %} {% render_field form.facility %}
{% render_field form.asn %} {% render_field form.asn %}
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><strong>Contact Info</strong></div> <div class="panel-heading"><strong>Contact Info</strong></div>
<div class="panel-body"> <div class="panel-body">

View File

@ -13,12 +13,18 @@
<div class="panel-heading"><strong>IP Address</strong></div> <div class="panel-heading"><strong>IP Address</strong></div>
<div class="panel-body"> <div class="panel-body">
{% render_field form.address %} {% render_field form.address %}
{% render_field form.vrf %}
{% render_field form.tenant %}
{% render_field form.status %} {% render_field form.status %}
{% render_field form.vrf %}
{% render_field form.description %} {% render_field form.description %}
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<strong>Interface Assignment</strong> <strong>Interface Assignment</strong>

View File

@ -6,14 +6,20 @@
<div class="panel-heading"><strong>Prefix</strong></div> <div class="panel-heading"><strong>Prefix</strong></div>
<div class="panel-body"> <div class="panel-body">
{% render_field form.prefix %} {% render_field form.prefix %}
{% render_field form.status %}
{% render_field form.vrf %} {% render_field form.vrf %}
{% render_field form.tenant %}
{% render_field form.site %} {% render_field form.site %}
{% render_field form.vlan %} {% render_field form.vlan %}
{% render_field form.status %}
{% render_field form.role %} {% render_field form.role %}
{% render_field form.is_pool %}
{% render_field form.description %} {% render_field form.description %}
{% render_field form.is_pool %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div> </div>
</div> </div>
{% if form.custom_fields %} {% if form.custom_fields %}

View File

@ -9,12 +9,18 @@
{% render_field form.group %} {% render_field form.group %}
{% render_field form.vid %} {% render_field form.vid %}
{% render_field form.name %} {% render_field form.name %}
{% render_field form.tenant %}
{% render_field form.status %} {% render_field form.status %}
{% render_field form.role %} {% render_field form.role %}
{% render_field form.description %} {% render_field form.description %}
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
{% if form.custom_fields %} {% if form.custom_fields %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><strong>Custom Fields</strong></div> <div class="panel-heading"><strong>Custom Fields</strong></div>

View File

@ -7,11 +7,17 @@
<div class="panel-body"> <div class="panel-body">
{% render_field form.name %} {% render_field form.name %}
{% render_field form.rd %} {% render_field form.rd %}
{% render_field form.tenant %}
{% render_field form.enforce_unique %} {% render_field form.enforce_unique %}
{% render_field form.description %} {% render_field form.description %}
</div> </div>
</div> </div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Tenancy</strong></div>
<div class="panel-body">
{% render_field form.tenant_group %}
{% render_field form.tenant %}
</div>
</div>
{% if form.custom_fields %} {% if form.custom_fields %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><strong>Custom Fields</strong></div> <div class="panel-heading"><strong>Custom Fields</strong></div>

View File

@ -2,8 +2,10 @@ from django import forms
from django.db.models import Count from django.db.models import Count
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from utilities.forms import BootstrapMixin, BulkImportForm, CommentField, CSVDataField, FilterChoiceField, SlugField from utilities.forms import (
APISelect, BootstrapMixin, BulkImportForm, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, CSVDataField,
FilterChoiceField, SlugField,
)
from .models import Tenant, TenantGroup from .models import Tenant, TenantGroup
@ -61,3 +63,37 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
to_field_name='slug', to_field_name='slug',
null_option=(0, 'None') null_option=(0, 'None')
) )
#
# Tenancy form extension
#
class TenancyForm(ChainedFieldsMixin, forms.Form):
tenant_group = forms.ModelChoiceField(
queryset=TenantGroup.objects.all(),
required=False,
widget=forms.Select(
attrs={'filter-for': 'tenant', 'nullable': 'true'}
)
)
tenant = ChainedModelChoiceField(
queryset=Tenant.objects.all(),
chains={'group': 'tenant_group'},
required=False,
widget=APISelect(
api_url='/api/tenancy/tenants/?group_id={{tenant_group}}'
)
)
def __init__(self, *args, **kwargs):
# Initialize helper selector
instance = kwargs.get('instance')
if instance and instance.tenant is not None:
try:
kwargs['initial']['tenant_group'] = instance.tenant.group
except KeyError:
kwargs['initial'] = {'tenant_group': instance.tenant.group}
super(TenancyForm, self).__init__(*args, **kwargs)