|
@@ -20,7 +20,7 @@ from .models import (
|
|
|
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType,
|
|
|
Interface, IFACE_FF_CHOICES, IFACE_FF_LAG, IFACE_ORDERING_CHOICES, InterfaceConnection, InterfaceTemplate,
|
|
|
Manufacturer, Module, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES,
|
|
|
- RACK_WIDTH_CHOICES, Rack, RackGroup, RackReservation, RackRole, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD,
|
|
|
+ RACK_WIDTH_CHOICES, Rack, RackGroup, RackReservation, RackRole, Region, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD,
|
|
|
VIRTUAL_IFACE_TYPES
|
|
|
)
|
|
|
|
|
@@ -64,6 +64,18 @@ class DeviceComponentForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
|
|
|
#
|
|
|
+# Regions
|
|
|
+#
|
|
|
+
|
|
|
+class RegionForm(BootstrapMixin, forms.ModelForm):
|
|
|
+ slug = SlugField()
|
|
|
+
|
|
|
+ class Meta:
|
|
|
+ model = Region
|
|
|
+ fields = ['name', 'slug']
|
|
|
+
|
|
|
+
|
|
|
+#
|
|
|
# Sites
|
|
|
#
|
|
|
|
|
@@ -73,8 +85,10 @@ class SiteForm(BootstrapMixin, CustomFieldForm):
|
|
|
|
|
|
class Meta:
|
|
|
model = Site
|
|
|
- fields = ['name', 'slug', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address', 'contact_name',
|
|
|
- 'contact_phone', 'contact_email', 'comments']
|
|
|
+ fields = [
|
|
|
+ 'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address',
|
|
|
+ 'contact_name', 'contact_phone', 'contact_email', 'comments',
|
|
|
+ ]
|
|
|
widgets = {
|
|
|
'physical_address': SmallTextarea(attrs={'rows': 3}),
|
|
|
'shipping_address': SmallTextarea(attrs={'rows': 3}),
|
|
@@ -89,12 +103,22 @@ class SiteForm(BootstrapMixin, CustomFieldForm):
|
|
|
|
|
|
|
|
|
class SiteFromCSVForm(forms.ModelForm):
|
|
|
- tenant = forms.ModelChoiceField(Tenant.objects.all(), to_field_name='name', required=False,
|
|
|
- error_messages={'invalid_choice': 'Tenant not found.'})
|
|
|
+ region = forms.ModelChoiceField(
|
|
|
+ Region.objects.all(), to_field_name='name', required=False, error_messages={
|
|
|
+ 'invalid_choice': 'Tenant not found.'
|
|
|
+ }
|
|
|
+ )
|
|
|
+ tenant = forms.ModelChoiceField(
|
|
|
+ Tenant.objects.all(), to_field_name='name', required=False, error_messages={
|
|
|
+ 'invalid_choice': 'Tenant not found.'
|
|
|
+ }
|
|
|
+ )
|
|
|
|
|
|
class Meta:
|
|
|
model = Site
|
|
|
- fields = ['name', 'slug', 'tenant', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email']
|
|
|
+ fields = [
|
|
|
+ 'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email',
|
|
|
+ ]
|
|
|
|
|
|
|
|
|
class SiteImportForm(BootstrapMixin, BulkImportForm):
|
|
@@ -103,18 +127,27 @@ class SiteImportForm(BootstrapMixin, BulkImportForm):
|
|
|
|
|
|
class SiteBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
|
|
pk = forms.ModelMultipleChoiceField(queryset=Site.objects.all(), widget=forms.MultipleHiddenInput)
|
|
|
+ region = forms.ModelChoiceField(queryset=Region.objects.all(), required=False)
|
|
|
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
|
asn = forms.IntegerField(min_value=1, max_value=4294967295, required=False, label='ASN')
|
|
|
|
|
|
class Meta:
|
|
|
- nullable_fields = ['tenant', 'asn']
|
|
|
+ nullable_fields = ['region', 'tenant', 'asn']
|
|
|
|
|
|
|
|
|
class SiteFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|
|
model = Site
|
|
|
q = forms.CharField(required=False, label='Search')
|
|
|
- tenant = FilterChoiceField(queryset=Tenant.objects.annotate(filter_count=Count('sites')), to_field_name='slug',
|
|
|
- null_option=(0, 'None'))
|
|
|
+ region = FilterChoiceField(
|
|
|
+ queryset=Region.objects.annotate(filter_count=Count('sites')),
|
|
|
+ to_field_name='slug',
|
|
|
+ null_option=(0, 'None')
|
|
|
+ )
|
|
|
+ tenant = FilterChoiceField(
|
|
|
+ queryset=Tenant.objects.annotate(filter_count=Count('sites')),
|
|
|
+ to_field_name='slug',
|
|
|
+ null_option=(0, 'None')
|
|
|
+ )
|
|
|
|
|
|
|
|
|
#
|