Coverage for src/backend/InvenTree/part/migrations/0144_auto_20251203_1045.py: 51%
31 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1# Generated by Django 5.2.8 on 2025-12-03 10:45
3from django.db import migrations, models
4from django.db.models import deletion
7def update_parameter(apps, schema_editor):
8 """Data migration to update existing PartParameter records.
10 - Set 'model_type' to the ContentType for 'part.Part'
11 - Set 'model_id' to the existing 'part_id' value
12 """
14 PartParameter = apps.get_model("part", "PartParameter")
15 ContentType = apps.get_model("contenttypes", "ContentType")
17 part_content_type, created = ContentType.objects.get_or_create(
18 app_label="part",
19 model="part",
20 )
22 parameters_to_update = []
24 N = PartParameter.objects.count()
26 # Update any existing PartParameter object, setting the new fields
27 for parameter in PartParameter.objects.all(): 27 ↛ 28line 27 didn't jump to line 28 because the loop on line 27 never started
28 parameter.model_type = part_content_type
29 parameter.model_id = parameter.part_id
30 parameters_to_update.append(parameter)
32 if len(parameters_to_update) > 0: 32 ↛ 34line 32 didn't jump to line 34 because the condition on line 32 was never true
34 print(f"Updating {len(parameters_to_update)} PartParameter records.")
36 PartParameter.objects.bulk_update(
37 parameters_to_update,
38 fields=["model_type", "model_id"],
39 )
41 # Ensure that the number of updated records matches the total number of records
42 assert PartParameter.objects.count() == N
44 # Ensure that no PartParameter records have null model_type or model_id
45 assert PartParameter.objects.filter(model_type=None).count() == 0
46 assert PartParameter.objects.filter(model_id=None).count() == 0
49def reverse_update_parameter(apps, schema_editor):
50 """Reverse data migration to restore existing PartParameter records.
52 - Set 'part_id' to the existing 'model_id' value
53 """
55 PartParameter = apps.get_model("part", "PartParameter")
57 parmeters_to_update = []
59 for parameter in PartParameter.objects.all():
60 parameter.part = parameter.model_id
61 parmeters_to_update.append(parameter)
63 if len(parmeters_to_update) > 0:
65 print(f"Reversing update of {len(parmeters_to_update)} PartParameter records.")
67 PartParameter.objects.bulk_update(
68 parmeters_to_update,
69 fields=["part"],
70 )
73class Migration(migrations.Migration):
74 """Data migration for making the PartParameterTemplate and PartParameter models generic.
76 - Add new fields to the "PartParameterTemplate" and "PartParameter" models
77 - Migrate existing data to populate the new fields
78 - Make the new fields non-nullable (if appropriate)
79 - Remove any obsolete fields (if necessary)
80 """
82 atomic = False
84 dependencies = [
85 ("part", "0143_alter_part_image"),
86 ]
88 operations = [
89 # Add the new "enabled" field to the PartParameterTemplate model
90 migrations.AddField(
91 model_name="partparametertemplate",
92 name="enabled",
93 field=models.BooleanField(
94 default=True,
95 help_text="Is this parameter template enabled?",
96 verbose_name="Enabled",
97 ),
98 ),
99 # Add the "model_type" field to the PartParmaeterTemplate model
100 migrations.AddField(
101 model_name="partparametertemplate",
102 name="model_type",
103 field=models.ForeignKey(
104 blank=True, null=True,
105 help_text="Target model type for this parameter template",
106 on_delete=deletion.SET_NULL,
107 to="contenttypes.contenttype",
108 verbose_name="Model type",
109 ),
110 ),
111 # Add the "model_type" field to the PartParameter model
112 # Note: This field is initially nullable, to allow existing records to remain valid.
113 migrations.AddField(
114 model_name="partparameter",
115 name="model_type",
116 field=models.ForeignKey(
117 blank=True, null=True,
118 on_delete=deletion.CASCADE,
119 to="contenttypes.contenttype",
120 ),
121 ),
122 # Add the "model_id" field to the PartParameter model
123 # Note: This field is initially nullable, to allow existing records to remain valid.
124 migrations.AddField(
125 model_name="partparameter",
126 name="model_id",
127 field=models.PositiveIntegerField(
128 blank=True, null=True,
129 help_text="ID of the target model for this parameter",
130 verbose_name="Model ID",
131 )
132 ),
133 # Migrate existing PartParameter records to populate the new fields
134 migrations.RunPython(
135 update_parameter,
136 reverse_code=reverse_update_parameter,
137 ),
138 # Update the "model_type" field on the PartParameter model to be non-nullable
139 migrations.AlterField(
140 model_name="partparameter",
141 name="model_type",
142 field=models.ForeignKey(
143 on_delete=deletion.CASCADE,
144 to="contenttypes.contenttype",
145 ),
146 ),
147 # Update the "model_id" field on the PartParameter model to be non-nullable
148 migrations.AlterField(
149 model_name="partparameter",
150 name="model_id",
151 field=models.PositiveIntegerField(
152 help_text="ID of the target model for this parameter",
153 verbose_name="Model ID",
154 )
155 ),
156 # Remove the "unique_together" constraint on the PartParameter model
157 migrations.AlterUniqueTogether(
158 name="partparameter",
159 unique_together={('model_type', 'model_id', 'template')},
160 ),
161 ]