mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
359ae5d116
Fixes #5573
111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
from django.db import migrations
|
|
|
|
from extras.choices import CustomFieldTypeChoices
|
|
|
|
|
|
def deserialize_value(field, value):
|
|
"""
|
|
Convert serialized values to JSON equivalents.
|
|
"""
|
|
if field.type in (CustomFieldTypeChoices.TYPE_INTEGER):
|
|
return int(value)
|
|
if field.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
|
return bool(int(value))
|
|
if field.type == CustomFieldTypeChoices.TYPE_SELECT:
|
|
return field._choices.get(pk=int(value)).value
|
|
return value
|
|
|
|
|
|
def migrate_customfield_defaults(apps, schema_editor):
|
|
"""
|
|
Copy old serialized defaults to native JSON types.
|
|
"""
|
|
CustomField = apps.get_model('extras', 'CustomField')
|
|
|
|
for customfield in CustomField.objects.exclude(default=''):
|
|
try:
|
|
if customfield.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
|
value = int(customfield.default)
|
|
elif customfield.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
|
value = customfield.default in ['true', 'yes', '1']
|
|
else:
|
|
value = customfield.default
|
|
except ValueError:
|
|
raise ValueError(
|
|
f'Invalid default value "{customfield.default}" found for {customfield.type} '
|
|
f'custom field {customfield.name}'
|
|
)
|
|
CustomField.objects.filter(pk=customfield.pk).update(default2=value)
|
|
|
|
|
|
def migrate_customfieldchoices(apps, schema_editor):
|
|
"""
|
|
Collect all CustomFieldChoices for each applicable CustomField, and save them locally as an array on
|
|
the CustomField instance.
|
|
"""
|
|
CustomField = apps.get_model('extras', 'CustomField')
|
|
CustomFieldChoice = apps.get_model('extras', 'CustomFieldChoice')
|
|
|
|
for cf in CustomField.objects.filter(type='select'):
|
|
cf.choices = [
|
|
cfc.value for cfc in CustomFieldChoice.objects.filter(field=cf).order_by('weight', 'value')
|
|
]
|
|
cf.save()
|
|
|
|
|
|
def migrate_customfieldvalues(apps, schema_editor):
|
|
"""
|
|
Copy data from CustomFieldValues into the custom_field_data JSON field on each model instance.
|
|
"""
|
|
CustomFieldValue = apps.get_model('extras', 'CustomFieldValue')
|
|
|
|
for cfv in CustomFieldValue.objects.prefetch_related('field').exclude(serialized_value=''):
|
|
model = apps.get_model(cfv.obj_type.app_label, cfv.obj_type.model)
|
|
|
|
# Read and update custom field value for each instance
|
|
# TODO: This can be done more efficiently once .update() is supported for JSON fields
|
|
cf_data = model.objects.filter(pk=cfv.obj_id).values('custom_field_data').first()
|
|
try:
|
|
cf_data['custom_field_data'][cfv.field.name] = deserialize_value(cfv.field, cfv.serialized_value)
|
|
except Exception as e:
|
|
print(f'{cfv.field.name} ({cfv.field.type}): {cfv.serialized_value} ({cfv.pk})')
|
|
raise e
|
|
model.objects.filter(pk=cfv.obj_id).update(**cf_data)
|
|
|
|
|
|
def fix_filter_logic_values(apps, schema_editor):
|
|
"""
|
|
Fix invalid values for CustomField.filter_logic (see #5376)
|
|
"""
|
|
CustomField = apps.get_model('extras', 'CustomField')
|
|
|
|
CustomField.objects.filter(filter_logic="integer").update(filter_logic="loose")
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
dependencies = [
|
|
('circuits', '0020_custom_field_data'),
|
|
('dcim', '0117_custom_field_data'),
|
|
('extras', '0050_customfield_changes'),
|
|
('ipam', '0038_custom_field_data'),
|
|
('secrets', '0010_custom_field_data'),
|
|
('tenancy', '0010_custom_field_data'),
|
|
('virtualization', '0018_custom_field_data'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.RunPython(
|
|
code=migrate_customfield_defaults
|
|
),
|
|
migrations.RunPython(
|
|
code=migrate_customfieldchoices
|
|
),
|
|
migrations.RunPython(
|
|
code=migrate_customfieldvalues
|
|
),
|
|
migrations.RunPython(
|
|
code=fix_filter_logic_values
|
|
),
|
|
]
|