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

1# Generated by Django 5.2.8 on 2025-12-03 10:45 

2 

3from django.db import migrations, models 

4from django.db.models import deletion 

5 

6 

7def update_parameter(apps, schema_editor): 

8 """Data migration to update existing PartParameter records. 

9  

10 - Set 'model_type' to the ContentType for 'part.Part' 

11 - Set 'model_id' to the existing 'part_id' value 

12 """ 

13 

14 PartParameter = apps.get_model("part", "PartParameter") 

15 ContentType = apps.get_model("contenttypes", "ContentType") 

16 

17 part_content_type, created = ContentType.objects.get_or_create( 

18 app_label="part", 

19 model="part", 

20 ) 

21 

22 parameters_to_update = [] 

23 

24 N = PartParameter.objects.count() 

25 

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) 

31 

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

33 

34 print(f"Updating {len(parameters_to_update)} PartParameter records.") 

35 

36 PartParameter.objects.bulk_update( 

37 parameters_to_update, 

38 fields=["model_type", "model_id"], 

39 ) 

40 

41 # Ensure that the number of updated records matches the total number of records 

42 assert PartParameter.objects.count() == N 

43 

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 

47 

48 

49def reverse_update_parameter(apps, schema_editor): 

50 """Reverse data migration to restore existing PartParameter records. 

51  

52 - Set 'part_id' to the existing 'model_id' value 

53 """ 

54 

55 PartParameter = apps.get_model("part", "PartParameter") 

56 

57 parmeters_to_update = [] 

58 

59 for parameter in PartParameter.objects.all(): 

60 parameter.part = parameter.model_id 

61 parmeters_to_update.append(parameter) 

62 

63 if len(parmeters_to_update) > 0: 

64 

65 print(f"Reversing update of {len(parmeters_to_update)} PartParameter records.") 

66 

67 PartParameter.objects.bulk_update( 

68 parmeters_to_update, 

69 fields=["part"], 

70 ) 

71 

72 

73class Migration(migrations.Migration): 

74 """Data migration for making the PartParameterTemplate and PartParameter models generic. 

75  

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 """ 

81 

82 atomic = False 

83 

84 dependencies = [ 

85 ("part", "0143_alter_part_image"), 

86 ] 

87 

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 ]