@@ -3329,6 +3329,52 @@ def test_rename_field_unique_together(self):
3329
3329
self .assertColumnExists ("test_rnflut_pony" , "pink" )
3330
3330
self .assertColumnNotExists ("test_rnflut_pony" , "blue" )
3331
3331
3332
+ def test_rename_field_index_together (self ):
3333
+ app_label = "test_rnflit"
3334
+ operations = [
3335
+ migrations .CreateModel (
3336
+ "Pony" ,
3337
+ fields = [
3338
+ ("id" , models .AutoField (primary_key = True )),
3339
+ ("pink" , models .IntegerField (default = 3 )),
3340
+ ("weight" , models .FloatField ()),
3341
+ ],
3342
+ options = {
3343
+ "index_together" : [("weight" , "pink" )],
3344
+ },
3345
+ ),
3346
+ ]
3347
+ project_state = self .apply_operations (app_label , ProjectState (), operations )
3348
+
3349
+ operation = migrations .RenameField ("Pony" , "pink" , "blue" )
3350
+ new_state = project_state .clone ()
3351
+ operation .state_forwards ("test_rnflit" , new_state )
3352
+ self .assertIn ("blue" , new_state .models ["test_rnflit" , "pony" ].fields )
3353
+ self .assertNotIn ("pink" , new_state .models ["test_rnflit" , "pony" ].fields )
3354
+ # index_together has the renamed column.
3355
+ self .assertIn (
3356
+ "blue" , new_state .models ["test_rnflit" , "pony" ].options ["index_together" ][0 ]
3357
+ )
3358
+ self .assertNotIn (
3359
+ "pink" , new_state .models ["test_rnflit" , "pony" ].options ["index_together" ][0 ]
3360
+ )
3361
+
3362
+ # Rename field.
3363
+ self .assertColumnExists ("test_rnflit_pony" , "pink" )
3364
+ self .assertColumnNotExists ("test_rnflit_pony" , "blue" )
3365
+ with connection .schema_editor () as editor :
3366
+ operation .database_forwards ("test_rnflit" , editor , project_state , new_state )
3367
+ self .assertColumnExists ("test_rnflit_pony" , "blue" )
3368
+ self .assertColumnNotExists ("test_rnflit_pony" , "pink" )
3369
+ # The index constraint has been ported over.
3370
+ self .assertIndexExists ("test_rnflit_pony" , ["weight" , "blue" ])
3371
+ # Reversal.
3372
+ with connection .schema_editor () as editor :
3373
+ operation .database_backwards (
3374
+ "test_rnflit" , editor , new_state , project_state
3375
+ )
3376
+ self .assertIndexExists ("test_rnflit_pony" , ["weight" , "pink" ])
3377
+
3332
3378
def test_rename_field_with_db_column (self ):
3333
3379
project_state = self .apply_operations (
3334
3380
"test_rfwdbc" ,
@@ -3822,6 +3868,63 @@ def test_rename_index_arguments(self):
3822
3868
with self .assertRaisesMessage (ValueError , msg ):
3823
3869
migrations .RenameIndex ("Pony" , new_name = "new_idx_name" )
3824
3870
3871
+ def test_rename_index_unnamed_index (self ):
3872
+ app_label = "test_rninui"
3873
+ operations = [
3874
+ migrations .CreateModel (
3875
+ "Pony" ,
3876
+ fields = [
3877
+ ("id" , models .AutoField (primary_key = True )),
3878
+ ("pink" , models .IntegerField (default = 3 )),
3879
+ ("weight" , models .FloatField ()),
3880
+ ],
3881
+ options = {
3882
+ "index_together" : [("weight" , "pink" )],
3883
+ },
3884
+ ),
3885
+ ]
3886
+ project_state = self .apply_operations (app_label , ProjectState (), operations )
3887
+ table_name = app_label + "_pony"
3888
+ self .assertIndexNameNotExists (table_name , "new_pony_test_idx" )
3889
+ operation = migrations .RenameIndex (
3890
+ "Pony" , new_name = "new_pony_test_idx" , old_fields = ("weight" , "pink" )
3891
+ )
3892
+ self .assertEqual (
3893
+ operation .describe (),
3894
+ "Rename unnamed index for ('weight', 'pink') on Pony to new_pony_test_idx" ,
3895
+ )
3896
+ self .assertEqual (
3897
+ operation .migration_name_fragment ,
3898
+ "rename_pony_weight_pink_new_pony_test_idx" ,
3899
+ )
3900
+ new_state = project_state .clone ()
3901
+ operation .state_forwards (app_label , new_state )
3902
+ # Rename index.
3903
+ with connection .schema_editor () as editor :
3904
+ operation .database_forwards (app_label , editor , project_state , new_state )
3905
+ self .assertIndexNameExists (table_name , "new_pony_test_idx" )
3906
+ # Reverse is a no-op.
3907
+ with connection .schema_editor () as editor , self .assertNumQueries (0 ):
3908
+ operation .database_backwards (app_label , editor , new_state , project_state )
3909
+ self .assertIndexNameExists (table_name , "new_pony_test_idx" )
3910
+ # Reapply, RenameIndex operation is a noop when the old and new name
3911
+ # match.
3912
+ with connection .schema_editor () as editor :
3913
+ operation .database_forwards (app_label , editor , new_state , project_state )
3914
+ self .assertIndexNameExists (table_name , "new_pony_test_idx" )
3915
+ # Deconstruction.
3916
+ definition = operation .deconstruct ()
3917
+ self .assertEqual (definition [0 ], "RenameIndex" )
3918
+ self .assertEqual (definition [1 ], [])
3919
+ self .assertEqual (
3920
+ definition [2 ],
3921
+ {
3922
+ "model_name" : "Pony" ,
3923
+ "new_name" : "new_pony_test_idx" ,
3924
+ "old_fields" : ("weight" , "pink" ),
3925
+ },
3926
+ )
3927
+
3825
3928
def test_rename_index_unknown_unnamed_index (self ):
3826
3929
app_label = "test_rninuui"
3827
3930
project_state = self .set_up_test_model (app_label )
@@ -3892,6 +3995,33 @@ def test_rename_index_state_forwards(self):
3892
3995
self .assertIsNot (old_model , new_model )
3893
3996
self .assertEqual (new_model ._meta .indexes [0 ].name , "new_pony_pink_idx" )
3894
3997
3998
+ def test_rename_index_state_forwards_unnamed_index (self ):
3999
+ app_label = "test_rnidsfui"
4000
+ operations = [
4001
+ migrations .CreateModel (
4002
+ "Pony" ,
4003
+ fields = [
4004
+ ("id" , models .AutoField (primary_key = True )),
4005
+ ("pink" , models .IntegerField (default = 3 )),
4006
+ ("weight" , models .FloatField ()),
4007
+ ],
4008
+ options = {
4009
+ "index_together" : [("weight" , "pink" )],
4010
+ },
4011
+ ),
4012
+ ]
4013
+ project_state = self .apply_operations (app_label , ProjectState (), operations )
4014
+ old_model = project_state .apps .get_model (app_label , "Pony" )
4015
+ new_state = project_state .clone ()
4016
+
4017
+ operation = migrations .RenameIndex (
4018
+ "Pony" , new_name = "new_pony_pink_idx" , old_fields = ("weight" , "pink" )
4019
+ )
4020
+ operation .state_forwards (app_label , new_state )
4021
+ new_model = new_state .apps .get_model (app_label , "Pony" )
4022
+ self .assertIsNot (old_model , new_model )
4023
+ self .assertEqual (new_model ._meta .indexes [0 ].name , "new_pony_pink_idx" )
4024
+
3895
4025
@skipUnlessDBFeature ("supports_expression_indexes" )
3896
4026
def test_add_func_index (self ):
3897
4027
app_label = "test_addfuncin"
@@ -4011,6 +4141,58 @@ def test_alter_field_with_index(self):
4011
4141
# Ensure the index is still there
4012
4142
self .assertIndexExists ("test_alflin_pony" , ["pink" ])
4013
4143
4144
+ def test_alter_index_together (self ):
4145
+ """
4146
+ Tests the AlterIndexTogether operation.
4147
+ """
4148
+ project_state = self .set_up_test_model ("test_alinto" )
4149
+ # Test the state alteration
4150
+ operation = migrations .AlterIndexTogether ("Pony" , [("pink" , "weight" )])
4151
+ self .assertEqual (
4152
+ operation .describe (), "Alter index_together for Pony (1 constraint(s))"
4153
+ )
4154
+ self .assertEqual (
4155
+ operation .migration_name_fragment ,
4156
+ "alter_pony_index_together" ,
4157
+ )
4158
+ new_state = project_state .clone ()
4159
+ operation .state_forwards ("test_alinto" , new_state )
4160
+ self .assertEqual (
4161
+ len (
4162
+ project_state .models ["test_alinto" , "pony" ].options .get (
4163
+ "index_together" , set ()
4164
+ )
4165
+ ),
4166
+ 0 ,
4167
+ )
4168
+ self .assertEqual (
4169
+ len (
4170
+ new_state .models ["test_alinto" , "pony" ].options .get (
4171
+ "index_together" , set ()
4172
+ )
4173
+ ),
4174
+ 1 ,
4175
+ )
4176
+ # Make sure there's no matching index
4177
+ self .assertIndexNotExists ("test_alinto_pony" , ["pink" , "weight" ])
4178
+ # Test the database alteration
4179
+ with connection .schema_editor () as editor :
4180
+ operation .database_forwards ("test_alinto" , editor , project_state , new_state )
4181
+ self .assertIndexExists ("test_alinto_pony" , ["pink" , "weight" ])
4182
+ # And test reversal
4183
+ with connection .schema_editor () as editor :
4184
+ operation .database_backwards (
4185
+ "test_alinto" , editor , new_state , project_state
4186
+ )
4187
+ self .assertIndexNotExists ("test_alinto_pony" , ["pink" , "weight" ])
4188
+ # And deconstruction
4189
+ definition = operation .deconstruct ()
4190
+ self .assertEqual (definition [0 ], "AlterIndexTogether" )
4191
+ self .assertEqual (definition [1 ], [])
4192
+ self .assertEqual (
4193
+ definition [2 ], {"name" : "Pony" , "index_together" : {("pink" , "weight" )}}
4194
+ )
4195
+
4014
4196
def test_alter_index_together_remove (self ):
4015
4197
operation = migrations .AlterIndexTogether ("Pony" , None )
4016
4198
self .assertEqual (
@@ -4021,6 +4203,29 @@ def test_alter_index_together_remove(self):
4021
4203
"~ Alter index_together for Pony (0 constraint(s))" ,
4022
4204
)
4023
4205
4206
+ @skipUnlessDBFeature ("allows_multiple_constraints_on_same_fields" )
4207
+ def test_alter_index_together_remove_with_unique_together (self ):
4208
+ app_label = "test_alintoremove_wunto"
4209
+ table_name = "%s_pony" % app_label
4210
+ project_state = self .set_up_test_model (app_label , unique_together = True )
4211
+ self .assertUniqueConstraintExists (table_name , ["pink" , "weight" ])
4212
+ # Add index together.
4213
+ new_state = project_state .clone ()
4214
+ operation = migrations .AlterIndexTogether ("Pony" , [("pink" , "weight" )])
4215
+ operation .state_forwards (app_label , new_state )
4216
+ with connection .schema_editor () as editor :
4217
+ operation .database_forwards (app_label , editor , project_state , new_state )
4218
+ self .assertIndexExists (table_name , ["pink" , "weight" ])
4219
+ # Remove index together.
4220
+ project_state = new_state
4221
+ new_state = project_state .clone ()
4222
+ operation = migrations .AlterIndexTogether ("Pony" , set ())
4223
+ operation .state_forwards (app_label , new_state )
4224
+ with connection .schema_editor () as editor :
4225
+ operation .database_forwards (app_label , editor , project_state , new_state )
4226
+ self .assertIndexNotExists (table_name , ["pink" , "weight" ])
4227
+ self .assertUniqueConstraintExists (table_name , ["pink" , "weight" ])
4228
+
4024
4229
def test_add_constraint (self ):
4025
4230
project_state = self .set_up_test_model ("test_addconstraint" )
4026
4231
gt_check = models .Q (pink__gt = 2 )
0 commit comments