mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 17:38:37 -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'),
|
verbose_name=_('priority'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=CircuitPriorityChoices,
|
choices=CircuitPriorityChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
prerequisite_models = (
|
prerequisite_models = (
|
||||||
'circuits.Circuit',
|
'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'),
|
verbose_name=_('type'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=CableTypeChoices,
|
choices=CableTypeChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
status = models.CharField(
|
status = models.CharField(
|
||||||
verbose_name=_('status'),
|
verbose_name=_('status'),
|
||||||
@ -78,6 +79,7 @@ class Cable(PrimaryModel):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=CableLengthUnitChoices,
|
choices=CableLengthUnitChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
# Stores the normalized length (in meters) for database ordering
|
# Stores the normalized length (in meters) for database ordering
|
||||||
_abs_length = models.DecimalField(
|
_abs_length = models.DecimalField(
|
||||||
@ -206,7 +208,7 @@ class Cable(PrimaryModel):
|
|||||||
|
|
||||||
# Clear length_unit if no length is defined
|
# Clear length_unit if no length is defined
|
||||||
if self.length is None:
|
if self.length is None:
|
||||||
self.length_unit = ''
|
self.length_unit = None
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
@ -365,7 +367,7 @@ class CableTermination(ChangeLoggedModel):
|
|||||||
termination = self.termination._meta.model.objects.get(pk=self.termination_id)
|
termination = self.termination._meta.model.objects.get(pk=self.termination_id)
|
||||||
termination.snapshot()
|
termination.snapshot()
|
||||||
termination.cable = None
|
termination.cable = None
|
||||||
termination.cable_end = ''
|
termination.cable_end = None
|
||||||
termination.save()
|
termination.save()
|
||||||
|
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
@ -203,7 +203,8 @@ class ConsolePortTemplate(ModularComponentTemplateModel):
|
|||||||
verbose_name=_('type'),
|
verbose_name=_('type'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ConsolePortTypeChoices,
|
choices=ConsolePortTypeChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
component_model = ConsolePort
|
component_model = ConsolePort
|
||||||
@ -237,7 +238,8 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel):
|
|||||||
verbose_name=_('type'),
|
verbose_name=_('type'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ConsolePortTypeChoices,
|
choices=ConsolePortTypeChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
component_model = ConsoleServerPort
|
component_model = ConsoleServerPort
|
||||||
@ -272,7 +274,8 @@ class PowerPortTemplate(ModularComponentTemplateModel):
|
|||||||
verbose_name=_('type'),
|
verbose_name=_('type'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=PowerPortTypeChoices,
|
choices=PowerPortTypeChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
maximum_draw = models.PositiveIntegerField(
|
maximum_draw = models.PositiveIntegerField(
|
||||||
verbose_name=_('maximum draw'),
|
verbose_name=_('maximum draw'),
|
||||||
@ -334,7 +337,8 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
|
|||||||
verbose_name=_('type'),
|
verbose_name=_('type'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=PowerOutletTypeChoices,
|
choices=PowerOutletTypeChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
power_port = models.ForeignKey(
|
power_port = models.ForeignKey(
|
||||||
to='dcim.PowerPortTemplate',
|
to='dcim.PowerPortTemplate',
|
||||||
@ -348,6 +352,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=PowerOutletFeedLegChoices,
|
choices=PowerOutletFeedLegChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Phase (for three-phase feeds)')
|
help_text=_('Phase (for three-phase feeds)')
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -434,18 +439,21 @@ class InterfaceTemplate(ModularComponentTemplateModel):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=InterfacePoEModeChoices,
|
choices=InterfacePoEModeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('PoE mode')
|
verbose_name=_('PoE mode')
|
||||||
)
|
)
|
||||||
poe_type = models.CharField(
|
poe_type = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=InterfacePoETypeChoices,
|
choices=InterfacePoETypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('PoE type')
|
verbose_name=_('PoE type')
|
||||||
)
|
)
|
||||||
rf_role = models.CharField(
|
rf_role = models.CharField(
|
||||||
max_length=30,
|
max_length=30,
|
||||||
choices=WirelessRoleChoices,
|
choices=WirelessRoleChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('wireless role')
|
verbose_name=_('wireless role')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -142,8 +142,9 @@ class CabledObjectModel(models.Model):
|
|||||||
cable_end = models.CharField(
|
cable_end = models.CharField(
|
||||||
verbose_name=_('cable end'),
|
verbose_name=_('cable end'),
|
||||||
max_length=1,
|
max_length=1,
|
||||||
|
choices=CableEndChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
choices=CableEndChoices
|
null=True
|
||||||
)
|
)
|
||||||
mark_connected = models.BooleanField(
|
mark_connected = models.BooleanField(
|
||||||
verbose_name=_('mark connected'),
|
verbose_name=_('mark connected'),
|
||||||
@ -283,6 +284,7 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ConsolePortTypeChoices,
|
choices=ConsolePortTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Physical port type')
|
help_text=_('Physical port type')
|
||||||
)
|
)
|
||||||
speed = models.PositiveIntegerField(
|
speed = models.PositiveIntegerField(
|
||||||
@ -309,6 +311,7 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint,
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ConsolePortTypeChoices,
|
choices=ConsolePortTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Physical port type')
|
help_text=_('Physical port type')
|
||||||
)
|
)
|
||||||
speed = models.PositiveIntegerField(
|
speed = models.PositiveIntegerField(
|
||||||
@ -339,6 +342,7 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracking
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=PowerPortTypeChoices,
|
choices=PowerPortTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Physical port type')
|
help_text=_('Physical port type')
|
||||||
)
|
)
|
||||||
maximum_draw = models.PositiveIntegerField(
|
maximum_draw = models.PositiveIntegerField(
|
||||||
@ -454,6 +458,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=PowerOutletTypeChoices,
|
choices=PowerOutletTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Physical port type')
|
help_text=_('Physical port type')
|
||||||
)
|
)
|
||||||
power_port = models.ForeignKey(
|
power_port = models.ForeignKey(
|
||||||
@ -468,6 +473,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=PowerOutletFeedLegChoices,
|
choices=PowerOutletFeedLegChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Phase (for three-phase feeds)')
|
help_text=_('Phase (for three-phase feeds)')
|
||||||
)
|
)
|
||||||
color = ColorField(
|
color = ColorField(
|
||||||
@ -522,6 +528,7 @@ class BaseInterface(models.Model):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=InterfaceModeChoices,
|
choices=InterfaceModeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('IEEE 802.1Q tagging strategy')
|
help_text=_('IEEE 802.1Q tagging strategy')
|
||||||
)
|
)
|
||||||
parent = models.ForeignKey(
|
parent = models.ForeignKey(
|
||||||
@ -631,12 +638,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
|||||||
max_length=30,
|
max_length=30,
|
||||||
choices=WirelessRoleChoices,
|
choices=WirelessRoleChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('wireless role')
|
verbose_name=_('wireless role')
|
||||||
)
|
)
|
||||||
rf_channel = models.CharField(
|
rf_channel = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=WirelessChannelChoices,
|
choices=WirelessChannelChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('wireless channel')
|
verbose_name=_('wireless channel')
|
||||||
)
|
)
|
||||||
rf_channel_frequency = models.DecimalField(
|
rf_channel_frequency = models.DecimalField(
|
||||||
@ -665,12 +674,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=InterfacePoEModeChoices,
|
choices=InterfacePoEModeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('PoE mode')
|
verbose_name=_('PoE mode')
|
||||||
)
|
)
|
||||||
poe_type = models.CharField(
|
poe_type = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=InterfacePoETypeChoices,
|
choices=InterfacePoETypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('PoE type')
|
verbose_name=_('PoE type')
|
||||||
)
|
)
|
||||||
wireless_link = models.ForeignKey(
|
wireless_link = models.ForeignKey(
|
||||||
|
@ -118,6 +118,7 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=SubdeviceRoleChoices,
|
choices=SubdeviceRoleChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('parent/child status'),
|
verbose_name=_('parent/child status'),
|
||||||
help_text=_('Parent devices house child devices in device bays. Leave blank '
|
help_text=_('Parent devices house child devices in device bays. Leave blank '
|
||||||
'if this device type is neither a parent nor a child.')
|
'if this device type is neither a parent nor a child.')
|
||||||
@ -126,7 +127,8 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
|||||||
verbose_name=_('airflow'),
|
verbose_name=_('airflow'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=DeviceAirflowChoices,
|
choices=DeviceAirflowChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
front_image = models.ImageField(
|
front_image = models.ImageField(
|
||||||
upload_to='devicetype-images',
|
upload_to='devicetype-images',
|
||||||
@ -387,7 +389,8 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
|||||||
verbose_name=_('airflow'),
|
verbose_name=_('airflow'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ModuleAirflowChoices,
|
choices=ModuleAirflowChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
clone_fields = ('manufacturer', 'weight', 'weight_unit', 'airflow')
|
clone_fields = ('manufacturer', 'weight', 'weight_unit', 'airflow')
|
||||||
@ -632,6 +635,7 @@ class Device(
|
|||||||
face = models.CharField(
|
face = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
choices=DeviceFaceChoices,
|
choices=DeviceFaceChoices,
|
||||||
verbose_name=_('rack face')
|
verbose_name=_('rack face')
|
||||||
)
|
)
|
||||||
@ -645,7 +649,8 @@ class Device(
|
|||||||
verbose_name=_('airflow'),
|
verbose_name=_('airflow'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=DeviceAirflowChoices,
|
choices=DeviceAirflowChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
primary_ip4 = models.OneToOneField(
|
primary_ip4 = models.OneToOneField(
|
||||||
to='ipam.IPAddress',
|
to='ipam.IPAddress',
|
||||||
|
@ -83,7 +83,8 @@ class RackBase(WeightMixin, PrimaryModel):
|
|||||||
verbose_name=_('outer unit'),
|
verbose_name=_('outer unit'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=RackDimensionUnitChoices,
|
choices=RackDimensionUnitChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
mounting_depth = models.PositiveSmallIntegerField(
|
mounting_depth = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_('mounting depth'),
|
verbose_name=_('mounting depth'),
|
||||||
@ -188,7 +189,7 @@ class RackType(RackBase):
|
|||||||
|
|
||||||
# Clear unit if outer width & depth are not set
|
# Clear unit if outer width & depth are not set
|
||||||
if self.outer_width is None and self.outer_depth is None:
|
if self.outer_width is None and self.outer_depth is None:
|
||||||
self.outer_unit = ''
|
self.outer_unit = None
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
@ -242,6 +243,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
|||||||
choices=RackFormFactorChoices,
|
choices=RackFormFactorChoices,
|
||||||
max_length=50,
|
max_length=50,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('form factor')
|
verbose_name=_('form factor')
|
||||||
)
|
)
|
||||||
rack_type = models.ForeignKey(
|
rack_type = models.ForeignKey(
|
||||||
@ -317,7 +319,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
|||||||
verbose_name=_('airflow'),
|
verbose_name=_('airflow'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=RackAirflowChoices,
|
choices=RackAirflowChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generic relations
|
# Generic relations
|
||||||
@ -409,7 +412,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
|||||||
|
|
||||||
# Clear unit if outer width & depth are not set
|
# Clear unit if outer width & depth are not set
|
||||||
if self.outer_width is None and self.outer_depth is None:
|
if self.outer_width is None and self.outer_depth is None:
|
||||||
self.outer_unit = ''
|
self.outer_unit = None
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -871,7 +871,6 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
|
|||||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
|
||||||
def test_outer_unit(self):
|
def test_outer_unit(self):
|
||||||
self.assertEqual(Rack.objects.filter(outer_unit__isnull=False).count(), 5)
|
|
||||||
params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER}
|
params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER}
|
||||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
|
||||||
|
@ -592,7 +592,7 @@ class DeviceTypeTestCase(
|
|||||||
'part_number': '123ABC',
|
'part_number': '123ABC',
|
||||||
'u_height': 2,
|
'u_height': 2,
|
||||||
'is_full_depth': True,
|
'is_full_depth': True,
|
||||||
'subdevice_role': '', # CharField
|
'subdevice_role': None,
|
||||||
'comments': 'Some comments',
|
'comments': 'Some comments',
|
||||||
'tags': [t.pk for t in tags],
|
'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,
|
max_length=50,
|
||||||
choices=CustomFieldChoiceSetBaseChoices,
|
choices=CustomFieldChoiceSetBaseChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('Base set of predefined choices (optional)')
|
help_text=_('Base set of predefined choices (optional)')
|
||||||
)
|
)
|
||||||
extra_choices = ArrayField(
|
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,
|
max_length=50,
|
||||||
choices=FHRPGroupAuthTypeChoices,
|
choices=FHRPGroupAuthTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('authentication type')
|
verbose_name=_('authentication type')
|
||||||
)
|
)
|
||||||
auth_key = models.CharField(
|
auth_key = models.CharField(
|
||||||
|
@ -784,6 +784,7 @@ class IPAddress(ContactsMixin, PrimaryModel):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=IPAddressRoleChoices,
|
choices=IPAddressRoleChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
help_text=_('The functional role of this IP')
|
help_text=_('The functional role of this IP')
|
||||||
)
|
)
|
||||||
assigned_object_type = models.ForeignKey(
|
assigned_object_type = models.ForeignKey(
|
||||||
|
@ -23,6 +23,7 @@ class WeightMixin(models.Model):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=WeightUnitChoices,
|
choices=WeightUnitChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
# Stores the normalized weight (in grams) for database ordering
|
# Stores the normalized weight (in grams) for database ordering
|
||||||
_abs_weight = models.PositiveBigIntegerField(
|
_abs_weight = models.PositiveBigIntegerField(
|
||||||
@ -64,6 +65,7 @@ class DistanceMixin(models.Model):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=DistanceUnitChoices,
|
choices=DistanceUnitChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
# Stores the normalized distance (in meters) for database ordering
|
# Stores the normalized distance (in meters) for database ordering
|
||||||
_abs_distance = models.DecimalField(
|
_abs_distance = models.DecimalField(
|
||||||
@ -85,7 +87,7 @@ class DistanceMixin(models.Model):
|
|||||||
|
|
||||||
# Clear distance_unit if no distance is defined
|
# Clear distance_unit if no distance is defined
|
||||||
if self.distance is None:
|
if self.distance is None:
|
||||||
self.distance_unit = ''
|
self.distance_unit = None
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
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'),
|
verbose_name=_('priority'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ContactPriorityChoices,
|
choices=ContactPriorityChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
clone_fields = ('object_type', 'object_id', 'role', 'priority')
|
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(
|
authentication_algorithm = models.CharField(
|
||||||
verbose_name=_('authentication algorithm'),
|
verbose_name=_('authentication algorithm'),
|
||||||
choices=AuthenticationAlgorithmChoices,
|
choices=AuthenticationAlgorithmChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
group = models.PositiveSmallIntegerField(
|
group = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_('group'),
|
verbose_name=_('group'),
|
||||||
@ -76,7 +77,8 @@ class IKEPolicy(PrimaryModel):
|
|||||||
mode = models.CharField(
|
mode = models.CharField(
|
||||||
verbose_name=_('mode'),
|
verbose_name=_('mode'),
|
||||||
choices=IKEModeChoices,
|
choices=IKEModeChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
proposals = models.ManyToManyField(
|
proposals = models.ManyToManyField(
|
||||||
to='vpn.IKEProposal',
|
to='vpn.IKEProposal',
|
||||||
@ -128,12 +130,14 @@ class IPSecProposal(PrimaryModel):
|
|||||||
encryption_algorithm = models.CharField(
|
encryption_algorithm = models.CharField(
|
||||||
verbose_name=_('encryption'),
|
verbose_name=_('encryption'),
|
||||||
choices=EncryptionAlgorithmChoices,
|
choices=EncryptionAlgorithmChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
authentication_algorithm = models.CharField(
|
authentication_algorithm = models.CharField(
|
||||||
verbose_name=_('authentication'),
|
verbose_name=_('authentication'),
|
||||||
choices=AuthenticationAlgorithmChoices,
|
choices=AuthenticationAlgorithmChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
sa_lifetime_seconds = models.PositiveIntegerField(
|
sa_lifetime_seconds = models.PositiveIntegerField(
|
||||||
verbose_name=_('SA lifetime (seconds)'),
|
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,
|
max_length=50,
|
||||||
choices=WirelessAuthTypeChoices,
|
choices=WirelessAuthTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_("authentication type"),
|
verbose_name=_("authentication type"),
|
||||||
)
|
)
|
||||||
auth_cipher = models.CharField(
|
auth_cipher = models.CharField(
|
||||||
verbose_name=_('authentication cipher'),
|
verbose_name=_('authentication cipher'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=WirelessAuthCipherChoices,
|
choices=WirelessAuthCipherChoices,
|
||||||
blank=True
|
blank=True,
|
||||||
|
null=True
|
||||||
)
|
)
|
||||||
auth_psk = models.CharField(
|
auth_psk = models.CharField(
|
||||||
max_length=PSK_MAX_LENGTH,
|
max_length=PSK_MAX_LENGTH,
|
||||||
|
Loading…
Reference in New Issue
Block a user