瀏覽代碼

Rename and refactor CustomFieldForm

Jeremy Stretch 6 年之前
父節點
當前提交
bc7cf63958
共有 7 個文件被更改,包括 55 次插入52 次删除
  1. 5 5
      netbox/circuits/forms.py
  2. 10 10
      netbox/dcim/forms.py
  3. 16 13
      netbox/extras/forms.py
  4. 13 13
      netbox/ipam/forms.py
  5. 3 3
      netbox/secrets/forms.py
  6. 3 3
      netbox/tenancy/forms.py
  7. 5 5
      netbox/virtualization/forms.py

+ 5 - 5
netbox/circuits/forms.py

@@ -2,7 +2,7 @@ from django import forms
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
 from dcim.models import Region, Site
 from dcim.models import Region, Site
-from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from utilities.forms import (
 from utilities.forms import (
@@ -17,7 +17,7 @@ from .models import Circuit, CircuitTermination, CircuitType, Provider
 # Providers
 # Providers
 #
 #
 
 
-class ProviderForm(BootstrapMixin, CustomFieldForm):
+class ProviderForm(BootstrapMixin, CustomFieldModelForm):
     slug = SlugField()
     slug = SlugField()
     comments = CommentField()
     comments = CommentField()
     tags = TagField(
     tags = TagField(
@@ -46,7 +46,7 @@ class ProviderForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class ProviderCSVForm(CustomFieldForm):
+class ProviderCSVForm(CustomFieldModelForm):
     slug = SlugField()
     slug = SlugField()
 
 
     class Meta:
     class Meta:
@@ -160,7 +160,7 @@ class CircuitTypeCSVForm(forms.ModelForm):
 # Circuits
 # Circuits
 #
 #
 
 
-class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     comments = CommentField()
     comments = CommentField()
     tags = TagField(
     tags = TagField(
         required=False
         required=False
@@ -188,7 +188,7 @@ class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class CircuitCSVForm(CustomFieldForm):
+class CircuitCSVForm(CustomFieldModelForm):
     provider = forms.ModelChoiceField(
     provider = forms.ModelChoiceField(
         queryset=Provider.objects.all(),
         queryset=Provider.objects.all(),
         to_field_name='name',
         to_field_name='name',

+ 10 - 10
netbox/dcim/forms.py

@@ -13,7 +13,7 @@ from timezone_field import TimeZoneFormField
 
 
 from circuits.models import Circuit, Provider
 from circuits.models import Circuit, Provider
 from extras.forms import (
 from extras.forms import (
-    AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm, LocalConfigContextFilterForm
+    AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm, LocalConfigContextFilterForm
 )
 )
 from ipam.constants import BGP_ASN_MAX, BGP_ASN_MIN
 from ipam.constants import BGP_ASN_MAX, BGP_ASN_MIN
 from ipam.models import IPAddress, VLAN
 from ipam.models import IPAddress, VLAN
@@ -215,7 +215,7 @@ class RegionFilterForm(BootstrapMixin, forms.Form):
 # Sites
 # Sites
 #
 #
 
 
-class SiteForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class SiteForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     region = TreeNodeChoiceField(
     region = TreeNodeChoiceField(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),
         required=False,
         required=False,
@@ -263,7 +263,7 @@ class SiteForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class SiteCSVForm(CustomFieldForm):
+class SiteCSVForm(CustomFieldModelForm):
     status = CSVChoiceField(
     status = CSVChoiceField(
         choices=SiteStatusChoices,
         choices=SiteStatusChoices,
         required=False,
         required=False,
@@ -459,7 +459,7 @@ class RackRoleCSVForm(forms.ModelForm):
 # Racks
 # Racks
 #
 #
 
 
-class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     group = ChainedModelChoiceField(
     group = ChainedModelChoiceField(
         queryset=RackGroup.objects.all(),
         queryset=RackGroup.objects.all(),
         chains=(
         chains=(
@@ -504,7 +504,7 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class RackCSVForm(CustomFieldForm):
+class RackCSVForm(CustomFieldModelForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -897,7 +897,7 @@ class ManufacturerCSVForm(forms.ModelForm):
 # Device types
 # Device types
 #
 #
 
 
-class DeviceTypeForm(BootstrapMixin, CustomFieldForm):
+class DeviceTypeForm(BootstrapMixin, CustomFieldModelForm):
     slug = SlugField(
     slug = SlugField(
         slug_source='model'
         slug_source='model'
     )
     )
@@ -1516,7 +1516,7 @@ class PlatformCSVForm(forms.ModelForm):
 # Devices
 # Devices
 #
 #
 
 
-class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         widget=APISelect(
         widget=APISelect(
@@ -1724,7 +1724,7 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldForm):
             self.initial['rack'] = self.instance.parent_bay.device.rack_id
             self.initial['rack'] = self.instance.parent_bay.device.rack_id
 
 
 
 
-class BaseDeviceCSVForm(CustomFieldForm):
+class BaseDeviceCSVForm(CustomFieldModelForm):
     device_role = forms.ModelChoiceField(
     device_role = forms.ModelChoiceField(
         queryset=DeviceRole.objects.all(),
         queryset=DeviceRole.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -4241,7 +4241,7 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
 # Power feeds
 # Power feeds
 #
 #
 
 
-class PowerFeedForm(BootstrapMixin, CustomFieldForm):
+class PowerFeedForm(BootstrapMixin, CustomFieldModelForm):
     site = ChainedModelChoiceField(
     site = ChainedModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         required=False,
         required=False,
@@ -4286,7 +4286,7 @@ class PowerFeedForm(BootstrapMixin, CustomFieldForm):
             self.initial['site'] = self.instance.power_panel.site
             self.initial['site'] = self.instance.power_panel.site
 
 
 
 
-class PowerFeedCSVForm(CustomFieldForm):
+class PowerFeedCSVForm(CustomFieldModelForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         to_field_name='name',
         to_field_name='name',

+ 16 - 13
netbox/extras/forms.py

@@ -10,8 +10,8 @@ from dcim.models import DeviceRole, Platform, Region, Site
 from tenancy.models import Tenant, TenantGroup
 from tenancy.models import Tenant, TenantGroup
 from utilities.forms import (
 from utilities.forms import (
     add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
     add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
-    CustomFieldChoiceField, CommentField, ContentTypeSelect, DatePicker, DateTimePicker, FilterChoiceField,
-    LaxURLField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES,
+    CommentField, ContentTypeSelect, DatePicker, DateTimePicker, FilterChoiceField, LaxURLField, JSONField, SlugField,
+    StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES,
 )
 )
 from .choices import *
 from .choices import *
 from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag
 from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag
@@ -71,7 +71,7 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
                     default_choice = cf.choices.get(value=initial).pk
                     default_choice = cf.choices.get(value=initial).pk
                 except ObjectDoesNotExist:
                 except ObjectDoesNotExist:
                     pass
                     pass
-            field = CustomFieldChoiceField(
+            field = forms.TypedChoiceField(
                 choices=choices, coerce=int, required=cf.required, initial=default_choice, widget=StaticSelect2()
                 choices=choices, coerce=int, required=cf.required, initial=default_choice, widget=StaticSelect2()
             )
             )
 
 
@@ -93,21 +93,15 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
     return field_dict
     return field_dict
 
 
 
 
-class CustomFieldForm(forms.ModelForm):
+class CustomFieldModelForm(forms.ModelForm):
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
 
 
-        self.custom_fields = []
-        self.obj_type = ContentType.objects.get_for_model(self._meta.model)
-
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
 
 
-        # Add all applicable CustomFields to the form
-        custom_fields = []
-        for name, field in get_custom_fields_for_model(self.obj_type).items():
-            self.fields[name] = field
-            custom_fields.append(name)
-        self.custom_fields = custom_fields
+        # Append form fields for CustomFields
+        self.obj_type = ContentType.objects.get_for_model(self._meta.model)
+        self._append_customfield_fields()
 
 
         # If editing an existing object, initialize values for all custom fields
         # If editing an existing object, initialize values for all custom fields
         if self.instance.pk:
         if self.instance.pk:
@@ -118,6 +112,15 @@ class CustomFieldForm(forms.ModelForm):
             for cfv in existing_values:
             for cfv in existing_values:
                 self.initial['cf_{}'.format(str(cfv.field.name))] = cfv.serialized_value
                 self.initial['cf_{}'.format(str(cfv.field.name))] = cfv.serialized_value
 
 
+    def _append_customfield_fields(self):
+        """
+        Append form fields for all applicable CustomFields.
+        """
+        self.custom_fields = []
+        for name, field in get_custom_fields_for_model(self.obj_type).items():
+            self.fields[name] = field
+            self.custom_fields.append(name)
+
     def _save_custom_fields(self):
     def _save_custom_fields(self):
 
 
         for field_name in self.custom_fields:
         for field_name in self.custom_fields:

+ 13 - 13
netbox/ipam/forms.py

@@ -4,7 +4,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
 from dcim.models import Device, Interface, Rack, Region, Site
 from dcim.models import Device, Interface, Rack, Region, Site
-from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from utilities.forms import (
 from utilities.forms import (
@@ -31,7 +31,7 @@ IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([
 # VRFs
 # VRFs
 #
 #
 
 
-class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class VRFForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     tags = TagField(
     tags = TagField(
         required=False
         required=False
     )
     )
@@ -49,7 +49,7 @@ class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class VRFCSVForm(CustomFieldForm):
+class VRFCSVForm(CustomFieldModelForm):
     tenant = forms.ModelChoiceField(
     tenant = forms.ModelChoiceField(
         queryset=Tenant.objects.all(),
         queryset=Tenant.objects.all(),
         required=False,
         required=False,
@@ -144,7 +144,7 @@ class RIRFilterForm(BootstrapMixin, forms.Form):
 # Aggregates
 # Aggregates
 #
 #
 
 
-class AggregateForm(BootstrapMixin, CustomFieldForm):
+class AggregateForm(BootstrapMixin, CustomFieldModelForm):
     tags = TagField(
     tags = TagField(
         required=False
         required=False
     )
     )
@@ -166,7 +166,7 @@ class AggregateForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class AggregateCSVForm(CustomFieldForm):
+class AggregateCSVForm(CustomFieldModelForm):
     rir = forms.ModelChoiceField(
     rir = forms.ModelChoiceField(
         queryset=RIR.objects.all(),
         queryset=RIR.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -263,7 +263,7 @@ class RoleCSVForm(forms.ModelForm):
 # Prefixes
 # Prefixes
 #
 #
 
 
-class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         required=False,
         required=False,
@@ -341,7 +341,7 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         self.fields['vrf'].empty_label = 'Global'
         self.fields['vrf'].empty_label = 'Global'
 
 
 
 
-class PrefixCSVForm(CustomFieldForm):
+class PrefixCSVForm(CustomFieldModelForm):
     vrf = FlexibleModelChoiceField(
     vrf = FlexibleModelChoiceField(
         queryset=VRF.objects.all(),
         queryset=VRF.objects.all(),
         to_field_name='rd',
         to_field_name='rd',
@@ -584,7 +584,7 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
 # IP addresses
 # IP addresses
 #
 #
 
 
-class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm):
+class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModelForm):
     interface = forms.ModelChoiceField(
     interface = forms.ModelChoiceField(
         queryset=Interface.objects.all(),
         queryset=Interface.objects.all(),
         required=False
         required=False
@@ -751,7 +751,7 @@ class IPAddressBulkCreateForm(BootstrapMixin, forms.Form):
     )
     )
 
 
 
 
-class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
 
 
     class Meta:
     class Meta:
         model = IPAddress
         model = IPAddress
@@ -771,7 +771,7 @@ class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         self.fields['vrf'].empty_label = 'Global'
         self.fields['vrf'].empty_label = 'Global'
 
 
 
 
-class IPAddressCSVForm(CustomFieldForm):
+class IPAddressCSVForm(CustomFieldModelForm):
     vrf = FlexibleModelChoiceField(
     vrf = FlexibleModelChoiceField(
         queryset=VRF.objects.all(),
         queryset=VRF.objects.all(),
         to_field_name='rd',
         to_field_name='rd',
@@ -1087,7 +1087,7 @@ class VLANGroupFilterForm(BootstrapMixin, forms.Form):
 # VLANs
 # VLANs
 #
 #
 
 
-class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         required=False,
         required=False,
@@ -1135,7 +1135,7 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class VLANCSVForm(CustomFieldForm):
+class VLANCSVForm(CustomFieldModelForm):
     site = forms.ModelChoiceField(
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         queryset=Site.objects.all(),
         required=False,
         required=False,
@@ -1310,7 +1310,7 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
 # Services
 # Services
 #
 #
 
 
-class ServiceForm(BootstrapMixin, CustomFieldForm):
+class ServiceForm(BootstrapMixin, CustomFieldModelForm):
     port = forms.IntegerField(
     port = forms.IntegerField(
         min_value=SERVICE_PORT_MIN,
         min_value=SERVICE_PORT_MIN,
         max_value=SERVICE_PORT_MAX
         max_value=SERVICE_PORT_MAX

+ 3 - 3
netbox/secrets/forms.py

@@ -4,7 +4,7 @@ from django import forms
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
 from dcim.models import Device
 from dcim.models import Device
-from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldForm
+from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelForm
 from utilities.forms import (
 from utilities.forms import (
     APISelect, APISelectMultiple, BootstrapMixin, FilterChoiceField, FlexibleModelChoiceField, SlugField,
     APISelect, APISelectMultiple, BootstrapMixin, FilterChoiceField, FlexibleModelChoiceField, SlugField,
     StaticSelect2Multiple
     StaticSelect2Multiple
@@ -68,7 +68,7 @@ class SecretRoleCSVForm(forms.ModelForm):
 # Secrets
 # Secrets
 #
 #
 
 
-class SecretForm(BootstrapMixin, CustomFieldForm):
+class SecretForm(BootstrapMixin, CustomFieldModelForm):
     plaintext = forms.CharField(
     plaintext = forms.CharField(
         max_length=SECRET_PLAINTEXT_MAX_LENGTH,
         max_length=SECRET_PLAINTEXT_MAX_LENGTH,
         required=False,
         required=False,
@@ -116,7 +116,7 @@ class SecretForm(BootstrapMixin, CustomFieldForm):
             })
             })
 
 
 
 
-class SecretCSVForm(CustomFieldForm):
+class SecretCSVForm(CustomFieldModelForm):
     device = FlexibleModelChoiceField(
     device = FlexibleModelChoiceField(
         queryset=Device.objects.all(),
         queryset=Device.objects.all(),
         to_field_name='name',
         to_field_name='name',

+ 3 - 3
netbox/tenancy/forms.py

@@ -1,7 +1,7 @@
 from django import forms
 from django import forms
 from taggit.forms import TagField
 from taggit.forms import TagField
 
 
-from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm
 from utilities.forms import (
 from utilities.forms import (
     APISelect, APISelectMultiple, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField,
     APISelect, APISelectMultiple, BootstrapMixin, ChainedFieldsMixin, ChainedModelChoiceField, CommentField,
     FilterChoiceField, SlugField,
     FilterChoiceField, SlugField,
@@ -38,7 +38,7 @@ class TenantGroupCSVForm(forms.ModelForm):
 # Tenants
 # Tenants
 #
 #
 
 
-class TenantForm(BootstrapMixin, CustomFieldForm):
+class TenantForm(BootstrapMixin, CustomFieldModelForm):
     slug = SlugField()
     slug = SlugField()
     comments = CommentField()
     comments = CommentField()
     tags = TagField(
     tags = TagField(
@@ -57,7 +57,7 @@ class TenantForm(BootstrapMixin, CustomFieldForm):
         }
         }
 
 
 
 
-class TenantCSVForm(CustomFieldForm):
+class TenantCSVForm(CustomFieldModelForm):
     slug = SlugField()
     slug = SlugField()
     group = forms.ModelChoiceField(
     group = forms.ModelChoiceField(
         queryset=TenantGroup.objects.all(),
         queryset=TenantGroup.objects.all(),

+ 5 - 5
netbox/virtualization/forms.py

@@ -6,7 +6,7 @@ from dcim.choices import InterfaceModeChoices
 from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN
 from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN
 from dcim.forms import INTERFACE_MODE_HELP_TEXT
 from dcim.forms import INTERFACE_MODE_HELP_TEXT
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
 from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
-from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
+from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldModelForm, CustomFieldFilterForm
 from ipam.models import IPAddress, VLANGroup, VLAN
 from ipam.models import IPAddress, VLANGroup, VLAN
 from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.models import Tenant
 from tenancy.models import Tenant
@@ -74,7 +74,7 @@ class ClusterGroupCSVForm(forms.ModelForm):
 # Clusters
 # Clusters
 #
 #
 
 
-class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     comments = CommentField()
     comments = CommentField()
     tags = TagField(
     tags = TagField(
         required=False
         required=False
@@ -98,7 +98,7 @@ class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
         }
 
 
 
 
-class ClusterCSVForm(CustomFieldForm):
+class ClusterCSVForm(CustomFieldModelForm):
     type = forms.ModelChoiceField(
     type = forms.ModelChoiceField(
         queryset=ClusterType.objects.all(),
         queryset=ClusterType.objects.all(),
         to_field_name='name',
         to_field_name='name',
@@ -327,7 +327,7 @@ class ClusterRemoveDevicesForm(ConfirmationForm):
 # Virtual Machines
 # Virtual Machines
 #
 #
 
 
-class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
+class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
     cluster_group = forms.ModelChoiceField(
     cluster_group = forms.ModelChoiceField(
         queryset=ClusterGroup.objects.all(),
         queryset=ClusterGroup.objects.all(),
         required=False,
         required=False,
@@ -430,7 +430,7 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
             self.fields['primary_ip6'].widget.attrs['readonly'] = True
             self.fields['primary_ip6'].widget.attrs['readonly'] = True
 
 
 
 
-class VirtualMachineCSVForm(CustomFieldForm):
+class VirtualMachineCSVForm(CustomFieldModelForm):
     status = CSVChoiceField(
     status = CSVChoiceField(
         choices=VirtualMachineStatusChoices,
         choices=VirtualMachineStatusChoices,
         required=False,
         required=False,