mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Merge branch 'feature' into 7336-vlan-translation-feature
This commit is contained in:
commit
38fe3d319f
43
netbox/circuits/migrations/0046_charfield_null_choices.py
Normal file
43
netbox/circuits/migrations/0046_charfield_null_choices.py
Normal file
@ -0,0 +1,43 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
Circuit = apps.get_model('circuits', 'Circuit')
|
||||
CircuitGroupAssignment = apps.get_model('circuits', 'CircuitGroupAssignment')
|
||||
CircuitTermination = apps.get_model('circuits', 'CircuitTermination')
|
||||
|
||||
Circuit.objects.filter(distance_unit='').update(distance_unit=None)
|
||||
CircuitGroupAssignment.objects.filter(priority='').update(priority=None)
|
||||
CircuitTermination.objects.filter(cable_end='').update(cable_end=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('circuits', '0045_circuit_distance'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='circuit',
|
||||
name='distance_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='circuitgroupassignment',
|
||||
name='priority',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='circuittermination',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -187,7 +187,8 @@ class CircuitGroupAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin,
|
||||
verbose_name=_('priority'),
|
||||
max_length=50,
|
||||
choices=CircuitPriorityChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
prerequisite_models = (
|
||||
'circuits.Circuit',
|
||||
|
287
netbox/dcim/migrations/0194_charfield_null_choices.py
Normal file
287
netbox/dcim/migrations/0194_charfield_null_choices.py
Normal file
@ -0,0 +1,287 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
Cable = apps.get_model('dcim', 'Cable')
|
||||
ConsolePort = apps.get_model('dcim', 'ConsolePort')
|
||||
ConsolePortTemplate = apps.get_model('dcim', 'ConsolePortTemplate')
|
||||
ConsoleServerPort = apps.get_model('dcim', 'ConsoleServerPort')
|
||||
ConsoleServerPortTemplate = apps.get_model('dcim', 'ConsoleServerPortTemplate')
|
||||
Device = apps.get_model('dcim', 'Device')
|
||||
DeviceType = apps.get_model('dcim', 'DeviceType')
|
||||
FrontPort = apps.get_model('dcim', 'FrontPort')
|
||||
Interface = apps.get_model('dcim', 'Interface')
|
||||
InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate')
|
||||
ModuleType = apps.get_model('dcim', 'ModuleType')
|
||||
PowerFeed = apps.get_model('dcim', 'PowerFeed')
|
||||
PowerOutlet = apps.get_model('dcim', 'PowerOutlet')
|
||||
PowerOutletTemplate = apps.get_model('dcim', 'PowerOutletTemplate')
|
||||
PowerPort = apps.get_model('dcim', 'PowerPort')
|
||||
PowerPortTemplate = apps.get_model('dcim', 'PowerPortTemplate')
|
||||
Rack = apps.get_model('dcim', 'Rack')
|
||||
RackType = apps.get_model('dcim', 'RackType')
|
||||
RearPort = apps.get_model('dcim', 'RearPort')
|
||||
|
||||
Cable.objects.filter(length_unit='').update(length_unit=None)
|
||||
Cable.objects.filter(type='').update(type=None)
|
||||
ConsolePort.objects.filter(cable_end='').update(cable_end=None)
|
||||
ConsolePort.objects.filter(type='').update(type=None)
|
||||
ConsolePortTemplate.objects.filter(type='').update(type=None)
|
||||
ConsoleServerPort.objects.filter(cable_end='').update(cable_end=None)
|
||||
ConsoleServerPort.objects.filter(type='').update(type=None)
|
||||
ConsoleServerPortTemplate.objects.filter(type='').update(type=None)
|
||||
Device.objects.filter(airflow='').update(airflow=None)
|
||||
Device.objects.filter(face='').update(face=None)
|
||||
DeviceType.objects.filter(airflow='').update(airflow=None)
|
||||
DeviceType.objects.filter(subdevice_role='').update(subdevice_role=None)
|
||||
DeviceType.objects.filter(weight_unit='').update(weight_unit=None)
|
||||
FrontPort.objects.filter(cable_end='').update(cable_end=None)
|
||||
Interface.objects.filter(cable_end='').update(cable_end=None)
|
||||
Interface.objects.filter(mode='').update(mode=None)
|
||||
Interface.objects.filter(poe_mode='').update(poe_mode=None)
|
||||
Interface.objects.filter(poe_type='').update(poe_type=None)
|
||||
Interface.objects.filter(rf_channel='').update(rf_channel=None)
|
||||
Interface.objects.filter(rf_role='').update(rf_role=None)
|
||||
InterfaceTemplate.objects.filter(poe_mode='').update(poe_mode=None)
|
||||
InterfaceTemplate.objects.filter(poe_type='').update(poe_type=None)
|
||||
InterfaceTemplate.objects.filter(rf_role='').update(rf_role=None)
|
||||
ModuleType.objects.filter(airflow='').update(airflow=None)
|
||||
ModuleType.objects.filter(weight_unit='').update(weight_unit=None)
|
||||
PowerFeed.objects.filter(cable_end='').update(cable_end=None)
|
||||
PowerOutlet.objects.filter(cable_end='').update(cable_end=None)
|
||||
PowerOutlet.objects.filter(feed_leg='').update(feed_leg=None)
|
||||
PowerOutlet.objects.filter(type='').update(type=None)
|
||||
PowerOutletTemplate.objects.filter(feed_leg='').update(feed_leg=None)
|
||||
PowerOutletTemplate.objects.filter(type='').update(type=None)
|
||||
PowerPort.objects.filter(cable_end='').update(cable_end=None)
|
||||
PowerPort.objects.filter(type='').update(type=None)
|
||||
PowerPortTemplate.objects.filter(type='').update(type=None)
|
||||
Rack.objects.filter(airflow='').update(airflow=None)
|
||||
Rack.objects.filter(form_factor='').update(form_factor=None)
|
||||
Rack.objects.filter(outer_unit='').update(outer_unit=None)
|
||||
Rack.objects.filter(weight_unit='').update(weight_unit=None)
|
||||
RackType.objects.filter(outer_unit='').update(outer_unit=None)
|
||||
RackType.objects.filter(weight_unit='').update(weight_unit=None)
|
||||
RearPort.objects.filter(cable_end='').update(cable_end=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0193_poweroutlet_color'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cable',
|
||||
name='length_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cable',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleport',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleport',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleporttemplate',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleserverport',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleserverport',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleserverporttemplate',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='airflow',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='face',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='airflow',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='subdevice_role',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='weight_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='frontport',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='mode',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='poe_mode',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='poe_type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='rf_channel',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='rf_role',
|
||||
field=models.CharField(blank=True, max_length=30, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interfacetemplate',
|
||||
name='poe_mode',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interfacetemplate',
|
||||
name='poe_type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interfacetemplate',
|
||||
name='rf_role',
|
||||
field=models.CharField(blank=True, max_length=30, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='moduletype',
|
||||
name='airflow',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='moduletype',
|
||||
name='weight_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='powerfeed',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poweroutlet',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poweroutlet',
|
||||
name='feed_leg',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poweroutlet',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poweroutlettemplate',
|
||||
name='feed_leg',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poweroutlettemplate',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='powerport',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='powerport',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='powerporttemplate',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rack',
|
||||
name='airflow',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rack',
|
||||
name='form_factor',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rack',
|
||||
name='outer_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rack',
|
||||
name='weight_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='racktype',
|
||||
name='outer_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='racktype',
|
||||
name='weight_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rearport',
|
||||
name='cable_end',
|
||||
field=models.CharField(blank=True, max_length=1, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -42,7 +42,8 @@ class Cable(PrimaryModel):
|
||||
verbose_name=_('type'),
|
||||
max_length=50,
|
||||
choices=CableTypeChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
status = models.CharField(
|
||||
verbose_name=_('status'),
|
||||
@ -78,6 +79,7 @@ class Cable(PrimaryModel):
|
||||
max_length=50,
|
||||
choices=CableLengthUnitChoices,
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
# Stores the normalized length (in meters) for database ordering
|
||||
_abs_length = models.DecimalField(
|
||||
@ -206,7 +208,7 @@ class Cable(PrimaryModel):
|
||||
|
||||
# Clear length_unit if no length is defined
|
||||
if self.length is None:
|
||||
self.length_unit = ''
|
||||
self.length_unit = None
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@ -365,7 +367,7 @@ class CableTermination(ChangeLoggedModel):
|
||||
termination = self.termination._meta.model.objects.get(pk=self.termination_id)
|
||||
termination.snapshot()
|
||||
termination.cable = None
|
||||
termination.cable_end = ''
|
||||
termination.cable_end = None
|
||||
termination.save()
|
||||
|
||||
super().delete(*args, **kwargs)
|
||||
|
@ -203,7 +203,8 @@ class ConsolePortTemplate(ModularComponentTemplateModel):
|
||||
verbose_name=_('type'),
|
||||
max_length=50,
|
||||
choices=ConsolePortTypeChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
component_model = ConsolePort
|
||||
@ -237,7 +238,8 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel):
|
||||
verbose_name=_('type'),
|
||||
max_length=50,
|
||||
choices=ConsolePortTypeChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
component_model = ConsoleServerPort
|
||||
@ -272,7 +274,8 @@ class PowerPortTemplate(ModularComponentTemplateModel):
|
||||
verbose_name=_('type'),
|
||||
max_length=50,
|
||||
choices=PowerPortTypeChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
maximum_draw = models.PositiveIntegerField(
|
||||
verbose_name=_('maximum draw'),
|
||||
@ -334,7 +337,8 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
|
||||
verbose_name=_('type'),
|
||||
max_length=50,
|
||||
choices=PowerOutletTypeChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
power_port = models.ForeignKey(
|
||||
to='dcim.PowerPortTemplate',
|
||||
@ -348,6 +352,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
|
||||
max_length=50,
|
||||
choices=PowerOutletFeedLegChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Phase (for three-phase feeds)')
|
||||
)
|
||||
|
||||
@ -434,18 +439,21 @@ class InterfaceTemplate(ModularComponentTemplateModel):
|
||||
max_length=50,
|
||||
choices=InterfacePoEModeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('PoE mode')
|
||||
)
|
||||
poe_type = models.CharField(
|
||||
max_length=50,
|
||||
choices=InterfacePoETypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('PoE type')
|
||||
)
|
||||
rf_role = models.CharField(
|
||||
max_length=30,
|
||||
choices=WirelessRoleChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('wireless role')
|
||||
)
|
||||
|
||||
|
@ -142,8 +142,9 @@ class CabledObjectModel(models.Model):
|
||||
cable_end = models.CharField(
|
||||
verbose_name=_('cable end'),
|
||||
max_length=1,
|
||||
choices=CableEndChoices,
|
||||
blank=True,
|
||||
choices=CableEndChoices
|
||||
null=True
|
||||
)
|
||||
mark_connected = models.BooleanField(
|
||||
verbose_name=_('mark connected'),
|
||||
@ -283,6 +284,7 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
||||
max_length=50,
|
||||
choices=ConsolePortTypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
speed = models.PositiveIntegerField(
|
||||
@ -309,6 +311,7 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint,
|
||||
max_length=50,
|
||||
choices=ConsolePortTypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
speed = models.PositiveIntegerField(
|
||||
@ -339,6 +342,7 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracking
|
||||
max_length=50,
|
||||
choices=PowerPortTypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
maximum_draw = models.PositiveIntegerField(
|
||||
@ -454,6 +458,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
||||
max_length=50,
|
||||
choices=PowerOutletTypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
power_port = models.ForeignKey(
|
||||
@ -468,6 +473,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
||||
max_length=50,
|
||||
choices=PowerOutletFeedLegChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Phase (for three-phase feeds)')
|
||||
)
|
||||
color = ColorField(
|
||||
@ -522,6 +528,7 @@ class BaseInterface(models.Model):
|
||||
max_length=50,
|
||||
choices=InterfaceModeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('IEEE 802.1Q tagging strategy')
|
||||
)
|
||||
parent = models.ForeignKey(
|
||||
@ -631,12 +638,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
||||
max_length=30,
|
||||
choices=WirelessRoleChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('wireless role')
|
||||
)
|
||||
rf_channel = models.CharField(
|
||||
max_length=50,
|
||||
choices=WirelessChannelChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('wireless channel')
|
||||
)
|
||||
rf_channel_frequency = models.DecimalField(
|
||||
@ -665,12 +674,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
||||
max_length=50,
|
||||
choices=InterfacePoEModeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('PoE mode')
|
||||
)
|
||||
poe_type = models.CharField(
|
||||
max_length=50,
|
||||
choices=InterfacePoETypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('PoE type')
|
||||
)
|
||||
wireless_link = models.ForeignKey(
|
||||
|
@ -118,6 +118,7 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
||||
max_length=50,
|
||||
choices=SubdeviceRoleChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('parent/child status'),
|
||||
help_text=_('Parent devices house child devices in device bays. Leave blank '
|
||||
'if this device type is neither a parent nor a child.')
|
||||
@ -126,7 +127,8 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
||||
verbose_name=_('airflow'),
|
||||
max_length=50,
|
||||
choices=DeviceAirflowChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
front_image = models.ImageField(
|
||||
upload_to='devicetype-images',
|
||||
@ -387,7 +389,8 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
||||
verbose_name=_('airflow'),
|
||||
max_length=50,
|
||||
choices=ModuleAirflowChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
clone_fields = ('manufacturer', 'weight', 'weight_unit', 'airflow')
|
||||
@ -632,6 +635,7 @@ class Device(
|
||||
face = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
null=True,
|
||||
choices=DeviceFaceChoices,
|
||||
verbose_name=_('rack face')
|
||||
)
|
||||
@ -645,7 +649,8 @@ class Device(
|
||||
verbose_name=_('airflow'),
|
||||
max_length=50,
|
||||
choices=DeviceAirflowChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
primary_ip4 = models.OneToOneField(
|
||||
to='ipam.IPAddress',
|
||||
|
@ -83,7 +83,8 @@ class RackBase(WeightMixin, PrimaryModel):
|
||||
verbose_name=_('outer unit'),
|
||||
max_length=50,
|
||||
choices=RackDimensionUnitChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
mounting_depth = models.PositiveSmallIntegerField(
|
||||
verbose_name=_('mounting depth'),
|
||||
@ -188,7 +189,7 @@ class RackType(RackBase):
|
||||
|
||||
# Clear unit if outer width & depth are not set
|
||||
if self.outer_width is None and self.outer_depth is None:
|
||||
self.outer_unit = ''
|
||||
self.outer_unit = None
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@ -242,6 +243,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
||||
choices=RackFormFactorChoices,
|
||||
max_length=50,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('form factor')
|
||||
)
|
||||
rack_type = models.ForeignKey(
|
||||
@ -317,7 +319,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
||||
verbose_name=_('airflow'),
|
||||
max_length=50,
|
||||
choices=RackAirflowChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
# Generic relations
|
||||
@ -409,7 +412,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
||||
|
||||
# Clear unit if outer width & depth are not set
|
||||
if self.outer_width is None and self.outer_depth is None:
|
||||
self.outer_unit = ''
|
||||
self.outer_unit = None
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
@ -871,7 +871,6 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_outer_unit(self):
|
||||
self.assertEqual(Rack.objects.filter(outer_unit__isnull=False).count(), 5)
|
||||
params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
|
@ -592,7 +592,7 @@ class DeviceTypeTestCase(
|
||||
'part_number': '123ABC',
|
||||
'u_height': 2,
|
||||
'is_full_depth': True,
|
||||
'subdevice_role': '', # CharField
|
||||
'subdevice_role': None,
|
||||
'comments': 'Some comments',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
29
netbox/extras/migrations/0122_charfield_null_choices.py
Normal file
29
netbox/extras/migrations/0122_charfield_null_choices.py
Normal file
@ -0,0 +1,29 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
CustomFieldChoiceSet = apps.get_model('extras', 'CustomFieldChoiceSet')
|
||||
|
||||
CustomFieldChoiceSet.objects.filter(base_choices='').update(base_choices=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('extras', '0121_customfield_related_object_filter'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='customfieldchoiceset',
|
||||
name='base_choices',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -760,6 +760,7 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel
|
||||
max_length=50,
|
||||
choices=CustomFieldChoiceSetBaseChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('Base set of predefined choices (optional)')
|
||||
)
|
||||
extra_choices = ArrayField(
|
||||
|
36
netbox/ipam/migrations/0073_charfield_null_choices.py
Normal file
36
netbox/ipam/migrations/0073_charfield_null_choices.py
Normal file
@ -0,0 +1,36 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
FHRPGroup = apps.get_model('ipam', 'FHRPGroup')
|
||||
IPAddress = apps.get_model('ipam', 'IPAddress')
|
||||
|
||||
FHRPGroup.objects.filter(auth_type='').update(auth_type=None)
|
||||
IPAddress.objects.filter(role='').update(role=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ipam', '0072_prefix_cached_relations'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='fhrpgroup',
|
||||
name='auth_type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ipaddress',
|
||||
name='role',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -34,6 +34,7 @@ class FHRPGroup(PrimaryModel):
|
||||
max_length=50,
|
||||
choices=FHRPGroupAuthTypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('authentication type')
|
||||
)
|
||||
auth_key = models.CharField(
|
||||
|
@ -784,6 +784,7 @@ class IPAddress(ContactsMixin, PrimaryModel):
|
||||
max_length=50,
|
||||
choices=IPAddressRoleChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_('The functional role of this IP')
|
||||
)
|
||||
assigned_object_type = models.ForeignKey(
|
||||
|
@ -23,6 +23,7 @@ class WeightMixin(models.Model):
|
||||
max_length=50,
|
||||
choices=WeightUnitChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
# Stores the normalized weight (in grams) for database ordering
|
||||
_abs_weight = models.PositiveBigIntegerField(
|
||||
@ -64,6 +65,7 @@ class DistanceMixin(models.Model):
|
||||
max_length=50,
|
||||
choices=DistanceUnitChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
# Stores the normalized distance (in meters) for database ordering
|
||||
_abs_distance = models.DecimalField(
|
||||
@ -85,7 +87,7 @@ class DistanceMixin(models.Model):
|
||||
|
||||
# Clear distance_unit if no distance is defined
|
||||
if self.distance is None:
|
||||
self.distance_unit = ''
|
||||
self.distance_unit = None
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
29
netbox/tenancy/migrations/0016_charfield_null_choices.py
Normal file
29
netbox/tenancy/migrations/0016_charfield_null_choices.py
Normal file
@ -0,0 +1,29 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
ContactAssignment = apps.get_model('tenancy', 'ContactAssignment')
|
||||
|
||||
ContactAssignment.objects.filter(priority='').update(priority=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tenancy', '0015_contactassignment_rename_content_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='contactassignment',
|
||||
name='priority',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -125,7 +125,8 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan
|
||||
verbose_name=_('priority'),
|
||||
max_length=50,
|
||||
choices=ContactPriorityChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
clone_fields = ('object_type', 'object_id', 'role', 'priority')
|
||||
|
@ -0,0 +1,29 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
VMInterface = apps.get_model('virtualization', 'VMInterface')
|
||||
|
||||
VMInterface.objects.filter(mode='').update(mode=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('virtualization', '0040_convert_disk_size'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='vminterface',
|
||||
name='mode',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
49
netbox/vpn/migrations/0006_charfield_null_choices.py
Normal file
49
netbox/vpn/migrations/0006_charfield_null_choices.py
Normal file
@ -0,0 +1,49 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
IKEPolicy = apps.get_model('vpn', 'IKEPolicy')
|
||||
IKEProposal = apps.get_model('vpn', 'IKEProposal')
|
||||
IPSecProposal = apps.get_model('vpn', 'IPSecProposal')
|
||||
|
||||
IKEPolicy.objects.filter(mode='').update(mode=None)
|
||||
IKEProposal.objects.filter(authentication_algorithm='').update(authentication_algorithm=None)
|
||||
IPSecProposal.objects.filter(authentication_algorithm='').update(authentication_algorithm=None)
|
||||
IPSecProposal.objects.filter(encryption_algorithm='').update(encryption_algorithm=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('vpn', '0005_rename_indexes'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='ikepolicy',
|
||||
name='mode',
|
||||
field=models.CharField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ikeproposal',
|
||||
name='authentication_algorithm',
|
||||
field=models.CharField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ipsecproposal',
|
||||
name='authentication_algorithm',
|
||||
field=models.CharField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ipsecproposal',
|
||||
name='encryption_algorithm',
|
||||
field=models.CharField(blank=True, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -35,7 +35,8 @@ class IKEProposal(PrimaryModel):
|
||||
authentication_algorithm = models.CharField(
|
||||
verbose_name=_('authentication algorithm'),
|
||||
choices=AuthenticationAlgorithmChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
group = models.PositiveSmallIntegerField(
|
||||
verbose_name=_('group'),
|
||||
@ -76,7 +77,8 @@ class IKEPolicy(PrimaryModel):
|
||||
mode = models.CharField(
|
||||
verbose_name=_('mode'),
|
||||
choices=IKEModeChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
proposals = models.ManyToManyField(
|
||||
to='vpn.IKEProposal',
|
||||
@ -128,12 +130,14 @@ class IPSecProposal(PrimaryModel):
|
||||
encryption_algorithm = models.CharField(
|
||||
verbose_name=_('encryption'),
|
||||
choices=EncryptionAlgorithmChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
authentication_algorithm = models.CharField(
|
||||
verbose_name=_('authentication'),
|
||||
choices=AuthenticationAlgorithmChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
sa_lifetime_seconds = models.PositiveIntegerField(
|
||||
verbose_name=_('SA lifetime (seconds)'),
|
||||
|
54
netbox/wireless/migrations/0010_charfield_null_choices.py
Normal file
54
netbox/wireless/migrations/0010_charfield_null_choices.py
Normal file
@ -0,0 +1,54 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_null_values(apps, schema_editor):
|
||||
"""
|
||||
Replace empty strings with null values.
|
||||
"""
|
||||
WirelessLAN = apps.get_model('wireless', 'WirelessLAN')
|
||||
WirelessLink = apps.get_model('wireless', 'WirelessLink')
|
||||
|
||||
WirelessLAN.objects.filter(auth_cipher='').update(auth_cipher=None)
|
||||
WirelessLAN.objects.filter(auth_type='').update(auth_type=None)
|
||||
WirelessLink.objects.filter(auth_cipher='').update(auth_cipher=None)
|
||||
WirelessLink.objects.filter(auth_type='').update(auth_type=None)
|
||||
WirelessLink.objects.filter(distance_unit='').update(distance_unit=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wireless', '0009_wirelesslink_distance'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='wirelesslan',
|
||||
name='auth_cipher',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wirelesslan',
|
||||
name='auth_type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wirelesslink',
|
||||
name='auth_cipher',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wirelesslink',
|
||||
name='auth_type',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wirelesslink',
|
||||
name='distance_unit',
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=set_null_values,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -24,13 +24,15 @@ class WirelessAuthenticationBase(models.Model):
|
||||
max_length=50,
|
||||
choices=WirelessAuthTypeChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_("authentication type"),
|
||||
)
|
||||
auth_cipher = models.CharField(
|
||||
verbose_name=_('authentication cipher'),
|
||||
max_length=50,
|
||||
choices=WirelessAuthCipherChoices,
|
||||
blank=True
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
auth_psk = models.CharField(
|
||||
max_length=PSK_MAX_LENGTH,
|
||||
|
Loading…
Reference in New Issue
Block a user