def test_render_project_dependencies(self): """ Tests that the ProjectState render method correctly renders models to account for inter-model base dependencies. """ new_apps = Apps() class A(models.Model): class Meta: app_label = "migrations" apps = new_apps class B(A): class Meta: app_label = "migrations" apps = new_apps class C(B): class Meta: app_label = "migrations" apps = new_apps class D(A): class Meta: app_label = "migrations" apps = new_apps class E(B): class Meta: app_label = "migrations" apps = new_apps proxy = True class F(D): class Meta: app_label = "migrations" apps = new_apps proxy = True # Make a ProjectState and render it project_state = ProjectState() project_state.add_model_state(ModelState.from_model(A)) project_state.add_model_state(ModelState.from_model(B)) project_state.add_model_state(ModelState.from_model(C)) project_state.add_model_state(ModelState.from_model(D)) project_state.add_model_state(ModelState.from_model(E)) project_state.add_model_state(ModelState.from_model(F)) final_apps = project_state.render() self.assertEqual(len(final_apps.get_models()), 6) # Now make an invalid ProjectState and make sure it fails project_state = ProjectState() project_state.add_model_state(ModelState.from_model(A)) project_state.add_model_state(ModelState.from_model(B)) project_state.add_model_state(ModelState.from_model(C)) project_state.add_model_state(ModelState.from_model(F)) with self.assertRaises(InvalidBasesError): project_state.render()
def test_remove_relations(self): """ #24225 - Tests that relations between models are updated while remaining the relations and references for models of an old state. """ new_apps = Apps() class A(models.Model): class Meta: app_label = "something" apps = new_apps class B(models.Model): to_a = models.ForeignKey(A, models.CASCADE) class Meta: app_label = "something" apps = new_apps def get_model_a(state): return [ mod for mod in state.apps.get_models() if mod._meta.model_name == 'a' ][0] project_state = ProjectState() project_state.add_model(ModelState.from_model(A)) project_state.add_model(ModelState.from_model(B)) self.assertEqual(len(get_model_a(project_state)._meta.related_objects), 1) old_state = project_state.clone() operation = RemoveField("b", "to_a") operation.state_forwards("something", project_state) # Tests that model from old_state still has the relation model_a_old = get_model_a(old_state) model_a_new = get_model_a(project_state) self.assertIsNot(model_a_old, model_a_new) self.assertEqual(len(model_a_old._meta.related_objects), 1) self.assertEqual(len(model_a_new._meta.related_objects), 0) # Same test for deleted model project_state = ProjectState() project_state.add_model(ModelState.from_model(A)) project_state.add_model(ModelState.from_model(B)) old_state = project_state.clone() operation = DeleteModel("b") operation.state_forwards("something", project_state) model_a_old = get_model_a(old_state) model_a_new = get_model_a(project_state) self.assertIsNot(model_a_old, model_a_new) self.assertEqual(len(model_a_old._meta.related_objects), 1) self.assertEqual(len(model_a_new._meta.related_objects), 0)
def set_up_test_model(self, app_label, second_model=False, related_model=False): """ Creates a test model state and database table. """ # Delete the tables if they already exist with connection.cursor() as cursor: try: cursor.execute("DROP TABLE %s_pony" % app_label) except: pass try: cursor.execute("DROP TABLE %s_stable" % app_label) except: pass # Make the "current" state operations = [ migrations.CreateModel( "Pony", [ ("id", models.AutoField(primary_key=True)), ("pink", models.IntegerField(default=3)), ("weight", models.FloatField()), ], ) ] if second_model: operations.append( migrations.CreateModel( "Stable", [("id", models.AutoField(primary_key=True))])) if related_model: operations.append( migrations.CreateModel( "Rider", [ ("id", models.AutoField(primary_key=True)), ("pony", models.ForeignKey("Pony")), ], )) project_state = ProjectState() for operation in operations: operation.state_forwards(app_label, project_state) # Set up the database with connection.schema_editor() as editor: for operation in operations: operation.database_forwards(app_label, editor, ProjectState(), project_state) return project_state
def test_migrations_not_applied_on_deferred_sql_failure(self): """Migrations are not recorded if deferred SQL application fails.""" class DeferredSQL: def __str__(self): raise DatabaseError('Failed to apply deferred SQL') class Migration(migrations.Migration): atomic = False def apply(self, project_state, schema_editor, collect_sql=False): schema_editor.deferred_sql.append(DeferredSQL()) executor = MigrationExecutor(connection) with self.assertRaisesMessage(DatabaseError, 'Failed to apply deferred SQL'): executor.apply_migration( ProjectState(), Migration('0001_initial', 'deferred_sql'), ) # The migration isn't recorded as applied since it failed. migration_recorder = MigrationRecorder(connection) self.assertIs( migration_recorder.migration_qs.filter( app='deferred_sql', name='0001_initial', ).exists(), False, )
def test_migrations_applied_and_recorded_atomically(self): """Migrations are applied and recorded atomically.""" class Migration(migrations.Migration): operations = [ migrations.CreateModel('model', [ ('id', models.AutoField(primary_key=True)), ]), ] executor = MigrationExecutor(connection) with mock.patch( 'django.db.migrations.executor.MigrationExecutor.record_migration' ) as record_migration: record_migration.side_effect = RuntimeError( 'Recording migration failed.') with self.assertRaisesMessage(RuntimeError, 'Recording migration failed.'): executor.apply_migration( ProjectState(), Migration('0001_initial', 'record_migration'), ) executor.migrate([('migrations', '0001_initial')]) # The migration isn't recorded as applied since it failed. migration_recorder = MigrationRecorder(connection) self.assertIs( migration_recorder.migration_qs.filter( app='record_migration', name='0001_initial', ).exists(), False, ) self.assertTableNotExists('record_migration_model')
def test_install_plugin(self): """ Test we can load the example plugin that every version of MySQL ships with. """ assert not plugin_exists("metadata_lock_info") state = ProjectState() operation = InstallPlugin("metadata_lock_info", "metadata_lock_info.so") assert ( operation.describe() == "Installs plugin metadata_lock_info from metadata_lock_info.so" ) new_state = state.clone() with connection.schema_editor() as editor: operation.database_forwards("testapp", editor, state, new_state) assert plugin_exists("metadata_lock_info") new_state = state.clone() with connection.schema_editor() as editor: operation.database_backwards("testapp", editor, new_state, state) assert not plugin_exists("metadata_lock_info")
def test_create(self): operation = CreateCollation("C_test", locale="C") self.assertEqual(operation.migration_name_fragment, "create_collation_c_test") self.assertEqual(operation.describe(), "Create collation C_test") project_state = ProjectState() new_state = project_state.clone() # Create a collation. with CaptureQueriesContext(connection) as captured_queries: with connection.schema_editor(atomic=False) as editor: operation.database_forwards( self.app_label, editor, project_state, new_state ) self.assertEqual(len(captured_queries), 1) self.assertIn("CREATE COLLATION", captured_queries[0]["sql"]) # Creating the same collation raises an exception. with self.assertRaisesMessage(ProgrammingError, "already exists"): with connection.schema_editor(atomic=True) as editor: operation.database_forwards( self.app_label, editor, project_state, new_state ) # Reversal. with CaptureQueriesContext(connection) as captured_queries: with connection.schema_editor(atomic=False) as editor: operation.database_backwards( self.app_label, editor, new_state, project_state ) self.assertEqual(len(captured_queries), 1) self.assertIn("DROP COLLATION", captured_queries[0]["sql"]) # Deconstruction. name, args, kwargs = operation.deconstruct() self.assertEqual(name, "CreateCollation") self.assertEqual(args, []) self.assertEqual(kwargs, {"name": "C_test", "locale": "C"})
def test_render(self): """ Tests rendering a ProjectState into an Apps. """ project_state = ProjectState() project_state.add_model(ModelState( app_label="migrations", name="Tag", fields=[ ("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=100)), ("hidden", models.BooleanField()), ], )) project_state.add_model(ModelState( app_label="migrations", name="SubTag", fields=[ ('tag_ptr', models.OneToOneField( 'migrations.Tag', models.CASCADE, auto_created=True, primary_key=True, to_field='id', serialize=False, )), ("awesome", models.BooleanField()), ], bases=("migrations.Tag",), )) base_mgr = models.Manager() mgr1 = FoodManager('a', 'b') mgr2 = FoodManager('x', 'y', c=3, d=4) project_state.add_model(ModelState( app_label="migrations", name="Food", fields=[ ("id", models.AutoField(primary_key=True)), ], managers=[ # The ordering we really want is objects, mgr1, mgr2 ('default', base_mgr), ('food_mgr2', mgr2), (b'food_mgr1', mgr1), ] )) new_apps = project_state.apps self.assertEqual(new_apps.get_model("migrations", "Tag")._meta.get_field("name").max_length, 100) self.assertIs(new_apps.get_model("migrations", "Tag")._meta.get_field("hidden").null, False) self.assertEqual(len(new_apps.get_model("migrations", "SubTag")._meta.local_fields), 2) Food = new_apps.get_model("migrations", "Food") self.assertEqual([mgr.name for mgr in Food._meta.managers], ['default', 'food_mgr1', 'food_mgr2']) self.assertTrue(all(isinstance(mgr.name, six.text_type) for mgr in Food._meta.managers)) self.assertEqual([mgr.__class__ for mgr in Food._meta.managers], [models.Manager, FoodManager, FoodManager])
def test_migrations_applied_and_recorded_atomically(self): """Migrations are applied and recorded atomically.""" class Migration(migrations.Migration): operations = [ migrations.CreateModel( "model", [ ("id", models.AutoField(primary_key=True)), ], ), ] executor = MigrationExecutor(connection) with mock.patch( "django.db.migrations.executor.MigrationExecutor.record_migration" ) as record_migration: record_migration.side_effect = RuntimeError( "Recording migration failed.") with self.assertRaisesMessage(RuntimeError, "Recording migration failed."): executor.apply_migration( ProjectState(), Migration("0001_initial", "record_migration"), ) executor.migrate([("migrations", "0001_initial")]) # The migration isn't recorded as applied since it failed. migration_recorder = MigrationRecorder(connection) self.assertIs( migration_recorder.migration_qs.filter( app="record_migration", name="0001_initial", ).exists(), False, ) self.assertTableNotExists("record_migration_model")
def test_self_relation(self): """ #24513 - Modifying an object pointing to itself would cause it to be rendered twice and thus breaking its related M2M through objects. """ class A(models.Model): to_a = models.ManyToManyField('something.A', symmetrical=False) class Meta: app_label = "something" def get_model_a(state): return [ mod for mod in state.apps.get_models() if mod._meta.model_name == 'a' ][0] project_state = ProjectState() project_state.add_model((ModelState.from_model(A))) self.assertEqual(len(get_model_a(project_state)._meta.related_objects), 1) old_state = project_state.clone() operation = AlterField(model_name="a", name="to_a", field=models.ManyToManyField("something.A", symmetrical=False, blank=True)) # At this point the model would be rendered twice causing its related # M2M through objects to point to an old copy and thus breaking their # attribute lookup. operation.state_forwards("something", project_state) model_a_old = get_model_a(old_state) model_a_new = get_model_a(project_state) self.assertIsNot(model_a_old, model_a_new) # Tests that the old model's _meta is still consistent field_to_a_old = model_a_old._meta.get_field("to_a") self.assertEqual(field_to_a_old.m2m_field_name(), "from_a") self.assertEqual(field_to_a_old.m2m_reverse_field_name(), "to_a") self.assertIs(field_to_a_old.related_model, model_a_old) self.assertIs( field_to_a_old.remote_field.through._meta.get_field( 'to_a').related_model, model_a_old) self.assertIs( field_to_a_old.remote_field.through._meta.get_field( 'from_a').related_model, model_a_old) # Tests that the new model's _meta is still consistent field_to_a_new = model_a_new._meta.get_field("to_a") self.assertEqual(field_to_a_new.m2m_field_name(), "from_a") self.assertEqual(field_to_a_new.m2m_reverse_field_name(), "to_a") self.assertIs(field_to_a_new.related_model, model_a_new) self.assertIs( field_to_a_new.remote_field.through._meta.get_field( 'to_a').related_model, model_a_new) self.assertIs( field_to_a_new.remote_field.through._meta.get_field( 'from_a').related_model, model_a_new)
def test_manager_refer_correct_model_version(self): """ #24147 - Tests that managers refer to the correct version of a historical model """ project_state = ProjectState() project_state.add_model( ModelState(app_label="migrations", name="Tag", fields=[ ("id", models.AutoField(primary_key=True)), ("hidden", models.BooleanField()), ], managers=[ ('food_mgr', FoodManager('a', 'b')), ('food_qs', FoodQuerySet.as_manager()), ])) old_model = project_state.apps.get_model('migrations', 'tag') new_state = project_state.clone() operation = RemoveField("tag", "hidden") operation.state_forwards("migrations", new_state) new_model = new_state.apps.get_model('migrations', 'tag') self.assertIsNot(old_model, new_model) self.assertIs(old_model, old_model.food_mgr.model) self.assertIs(old_model, old_model.food_qs.model) self.assertIs(new_model, new_model.food_mgr.model) self.assertIs(new_model, new_model.food_qs.model) self.assertIsNot(old_model.food_mgr, new_model.food_mgr) self.assertIsNot(old_model.food_qs, new_model.food_qs) self.assertIsNot(old_model.food_mgr.model, new_model.food_mgr.model) self.assertIsNot(old_model.food_qs.model, new_model.food_qs.model)
def _make_project_state(model_states): """Shortcut to make :see:ProjectState from a list of predefined models.""" project_state = ProjectState() for model_state in model_states: project_state.add_model(model_state.clone()) return project_state
def test_render(self): """ Tests rendering a ProjectState into an AppCache. """ project_state = ProjectState() project_state.add_model_state( ModelState( "migrations", "Tag", [ ("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=100)), ("hidden", models.BooleanField()), ], {}, None, )) new_app_cache = project_state.render() self.assertEqual( new_app_cache.get_model( "migrations", "Tag")._meta.get_field_by_name("name")[0].max_length, 100) self.assertEqual( new_app_cache.get_model( "migrations", "Tag")._meta.get_field_by_name("hidden")[0].null, False)
def _modify_app_models(*args, **kwargs): app_models = wrapped_func(*args, **kwargs) new_app_models = {} for model_key, model_value in six.iteritems(app_models.models): if model_key not in apps: new_app_models[model_key] = model_value return ProjectState(new_app_models)
def _test_create_model(self, app_label, should_run): """ Tests that CreateModel honours multi-db settings. """ operation = migrations.CreateModel( "Pony", [("id", models.AutoField(primary_key=True))], ) # Test the state alteration project_state = ProjectState() new_state = project_state.clone() operation.state_forwards(app_label, new_state) # Test the database alteration self.assertTableNotExists("%s_pony" % app_label) with connection.schema_editor() as editor: operation.database_forwards(app_label, editor, project_state, new_state) if should_run: self.assertTableExists("%s_pony" % app_label) else: self.assertTableNotExists("%s_pony" % app_label) # And test reversal with connection.schema_editor() as editor: operation.database_backwards(app_label, editor, new_state, project_state) self.assertTableNotExists("%s_pony" % app_label)
def test_registering_external_does_not_change_state(self): project_state_before_register = ProjectState() self._add_user_project_state_models(project_state_before_register) # Ensure User manager is use_in_migrations self.assertTrue(User.objects.use_in_migrations) project_state_after_register = ProjectState() self._add_user_project_state_models(project_state_after_register) executor = MigrationExecutor(connection) autodetector = MigrationAutodetector(project_state_before_register, project_state_after_register) changes = autodetector.changes(graph=executor.loader.graph) self.assertEqual({}, changes)
def test_alter_size_for_pk(self): setup_operations = [ migrations.CreateModel( 'Pony', [ ('name', models.CharField( max_length=10, default='', primary_key=True)), ], ) ] new_state = self.apply_operations('test', ProjectState(), setup_operations) operations = [ migrations.AlterField( model_name='Pony', name='name', field=models.CharField(max_length=20, default='', primary_key=True), ), ] with self.collect_sql() as sqls: self.apply_operations('test', new_state, operations) self.assertEqual([ '''ALTER TABLE "test_pony" DROP CONSTRAINT "test_pony_pkey";''', '''ALTER TABLE "test_pony" ALTER COLUMN "name" TYPE varchar(20);''', '''ALTER TABLE "test_pony" ADD CONSTRAINT "test_pony_name_2c070d2a_pk" PRIMARY KEY ("name");''', ], sqls)
def test_add_relations(self): """ #24573 - Adding relations to existing models should reload the referenced models too. """ class A(models.Model): class Meta: app_label = 'something' class B(A): class Meta: app_label = 'something' class C(models.Model): class Meta: app_label = 'something' project_state = ProjectState() project_state.add_model(ModelState.from_model(A)) project_state.add_model(ModelState.from_model(B)) project_state.add_model(ModelState.from_model(C)) project_state.apps # We need to work with rendered models old_state = project_state.clone() model_a_old = old_state.apps.get_model('something', 'A') model_b_old = old_state.apps.get_model('something', 'B') model_c_old = old_state.apps.get_model('something', 'C') # Check that the relations between the old models are correct self.assertIs( model_a_old._meta.get_field('b').related_model, model_b_old) self.assertIs( model_b_old._meta.get_field('a_ptr').related_model, model_a_old) operation = AddField( 'c', 'to_a', models.OneToOneField('something.A', related_name='from_c')) operation.state_forwards('something', project_state) model_a_new = project_state.apps.get_model('something', 'A') model_b_new = project_state.apps.get_model('something', 'B') model_c_new = project_state.apps.get_model('something', 'C') # Check that all models have changed self.assertIsNot(model_a_old, model_a_new) self.assertIsNot(model_b_old, model_b_new) self.assertIsNot(model_c_old, model_c_new) # Check that the relations between the old models still hold self.assertIs( model_a_old._meta.get_field('b').related_model, model_b_old) self.assertIs( model_b_old._meta.get_field('a_ptr').related_model, model_a_old) # Check that the relations between the new models correct self.assertIs( model_a_new._meta.get_field('b').related_model, model_b_new) self.assertIs( model_b_new._meta.get_field('a_ptr').related_model, model_a_new) self.assertIs( model_a_new._meta.get_field('from_c').related_model, model_c_new) self.assertIs( model_c_new._meta.get_field('to_a').related_model, model_a_new)
def _migrate_all_forwards(self, plan, full_plan, fake, fake_initial): """ Take a list of 2-tuples of the form (migration instance, False) and apply them in the order they occur in the full_plan. """ migrations_to_run = {m[0] for m in plan} state = ProjectState(real_apps=list(self.loader.unmigrated_apps)) for migration, _ in full_plan: if not migrations_to_run: # We remove every migration that we applied from this set so # that we can bail out once the last migration has been applied # and don't always run until the very end of the migration # process. break if migration in migrations_to_run: if "apps" not in state.__dict__: if self.progress_callback: self.progress_callback("render_start") state.apps # Render all -- performance critical if self.progress_callback: self.progress_callback("render_success") state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial) migrations_to_run.remove(migration) else: migration.mutate_state(state, preserve=False)
def test_ignore_order_wrt(self): """ Makes sure ProjectState doesn't include OrderWrt fields when making from existing models. """ new_apps = Apps() class Author(models.Model): name = models.TextField() class Meta: app_label = "migrations" apps = new_apps class Book(models.Model): author = models.ForeignKey(Author) class Meta: app_label = "migrations" apps = new_apps order_with_respect_to = "author" # Make a valid ProjectState and render it project_state = ProjectState() project_state.add_model_state(ModelState.from_model(Author)) project_state.add_model_state(ModelState.from_model(Book)) self.assertEqual( [ name for name, field in project_state.models["migrations", "book"].fields ], ["id", "author"], )
def test_demo_schemata_get_migrated(self): user = User.objects.create_user(**CREDENTIALS) schema = DemoSchema.objects.create(user=user, from_template=self.template) operation = migrations.CreateModel("Pony", [ ('pony_id', models.AutoField(primary_key=True)), ('pink', models.IntegerField(default=1)), ]) project_state = ProjectState() new_state = project_state.clone() operation.state_forwards('tests', new_state) schema.activate() self.assertFalse('tests_pony' in get_table_list()) with connection.schema_editor() as editor: operation.database_forwards('tests', editor, project_state, new_state) schema.activate() self.assertTrue('tests_pony' in get_table_list()) with connection.schema_editor() as editor: operation.database_backwards('tests', editor, new_state, project_state) schema.activate() self.assertFalse('tests_pony' in get_table_list())
def test_create(self): operation = CreateCollation('C_test', locale='C') self.assertEqual(operation.migration_name_fragment, 'create_collation_c_test') self.assertEqual(operation.describe(), 'Create collation C_test') project_state = ProjectState() new_state = project_state.clone() # Create a collation. with CaptureQueriesContext(connection) as captured_queries: with connection.schema_editor(atomic=False) as editor: operation.database_forwards(self.app_label, editor, project_state, new_state) self.assertEqual(len(captured_queries), 1) self.assertIn('CREATE COLLATION', captured_queries[0]['sql']) # Creating the same collation raises an exception. with self.assertRaisesMessage(ProgrammingError, 'already exists'): with connection.schema_editor(atomic=True) as editor: operation.database_forwards(self.app_label, editor, project_state, new_state) # Reversal. with CaptureQueriesContext(connection) as captured_queries: with connection.schema_editor(atomic=False) as editor: operation.database_backwards(self.app_label, editor, new_state, project_state) self.assertEqual(len(captured_queries), 1) self.assertIn('DROP COLLATION', captured_queries[0]['sql']) # Deconstruction. name, args, kwargs = operation.deconstruct() self.assertEqual(name, 'CreateCollation') self.assertEqual(args, []) self.assertEqual(kwargs, {'name': 'C_test', 'locale': 'C'})
def test_create_non_deterministic_collation(self): operation = CreateCollation( 'case_insensitive_test', 'und-u-ks-level2', provider='icu', deterministic=False, ) project_state = ProjectState() new_state = project_state.clone() # Create a collation. with CaptureQueriesContext(connection) as captured_queries: with connection.schema_editor(atomic=False) as editor: operation.database_forwards(self.app_label, editor, project_state, new_state) self.assertEqual(len(captured_queries), 1) self.assertIn('CREATE COLLATION', captured_queries[0]['sql']) # Reversal. with CaptureQueriesContext(connection) as captured_queries: with connection.schema_editor(atomic=False) as editor: operation.database_backwards(self.app_label, editor, new_state, project_state) self.assertEqual(len(captured_queries), 1) self.assertIn('DROP COLLATION', captured_queries[0]['sql']) # Deconstruction. name, args, kwargs = operation.deconstruct() self.assertEqual(name, 'CreateCollation') self.assertEqual(args, []) self.assertEqual( kwargs, { 'name': 'case_insensitive_test', 'locale': 'und-u-ks-level2', 'provider': 'icu', 'deterministic': False, })
def test_create_model(self): """ Tests that CreateModel honours multi-db settings. """ operation = migrations.CreateModel( "Pony", [ ("id", models.AutoField(primary_key=True)), ("pink", models.IntegerField(default=1)), ], ) # Test the state alteration project_state = ProjectState() new_state = project_state.clone() operation.state_forwards("test_crmo", new_state) # Test the database alteration self.assertTableNotExists("test_crmo_pony") with connection.schema_editor() as editor: operation.database_forwards("test_crmo", editor, project_state, new_state) self.assertTableNotExists("test_crmo_pony") # And test reversal with connection.schema_editor() as editor: operation.database_backwards("test_crmo", editor, new_state, project_state) self.assertTableNotExists("test_crmo_pony")
def test_create_model(self): """ Tests the CreateModel operation. Most other tests use this operation as part of setup, so check failures here first. """ operation = migrations.CreateModel( "Pony", [ ("id", models.AutoField(primary_key=True)), ("pink", models.IntegerField(default=1)), ], ) # Test the state alteration project_state = ProjectState() new_state = project_state.clone() operation.state_forwards("test_crmo", new_state) self.assertEqual(new_state.models["test_crmo", "pony"].name, "Pony") self.assertEqual(len(new_state.models["test_crmo", "pony"].fields), 2) # Test the database alteration self.assertTableNotExists("test_crmo_pony") with connection.schema_editor() as editor: operation.database_forwards("test_crmo", editor, project_state, new_state) self.assertTableExists("test_crmo_pony") # And test reversal with connection.schema_editor() as editor: operation.database_backwards("test_crmo", editor, new_state, project_state) self.assertTableNotExists("test_crmo_pony") # And deconstruction definition = operation.deconstruct() self.assertEqual(definition[0], "CreateModel") self.assertEqual(len(definition[1]), 2) self.assertEqual(len(definition[2]), 0) self.assertEqual(definition[1][0], "Pony")
def set_up_test_model(self, force_raster_creation=False): test_fields = [('id', models.AutoField(primary_key=True)), ('name', models.CharField(max_length=100, unique=True)), ('geom', fields.MultiPolygonField(srid=4326))] if connection.features.supports_raster or force_raster_creation: test_fields += [('rast', fields.RasterField(srid=4326))] operations = [migrations.CreateModel('Neighborhood', test_fields)] return self.apply_operations('gis', ProjectState(), operations)
def make_state(self, nodes=None, at_end=True, real_apps=None): """ Given a migrations node or nodes, return a complete ProjectState for it. If at_end is False, return the state before the migrations has run. If nodes is not provided, return the overall most current project state. """ if nodes is None: nodes = list(self.leaf_nodes()) if not nodes: return ProjectState() if not isinstance(nodes[0], tuple): nodes = [nodes] plan = self._generate_plan(nodes, at_end) project_state = ProjectState(real_apps=real_apps) for node in plan: project_state = self.nodes[node].mutate_state(project_state, preserve=False) return project_state
def test_repr(self): field = models.CharField(max_length=1) state = ModelState('app', 'Model', [('name', field)], bases=['app.A', 'app.B', 'app.C']) self.assertEqual(repr(state), "<ModelState: 'app.Model'>") project_state = ProjectState() project_state.add_model(state) with self.assertRaisesMessage(InvalidBasesError, "Cannot resolve bases for [<ModelState: 'app.Model'>]"): project_state.apps
def test_dangling_references_throw_error(self): new_apps = Apps() class Author(models.Model): name = models.TextField() class Meta: app_label = "migrations" apps = new_apps class Book(models.Model): author = models.ForeignKey(Author) class Meta: app_label = "migrations" apps = new_apps class Magazine(models.Model): authors = models.ManyToManyField(Author) class Meta: app_label = "migrations" apps = new_apps # Make a valid ProjectState and render it project_state = ProjectState() project_state.add_model_state(ModelState.from_model(Author)) project_state.add_model_state(ModelState.from_model(Book)) project_state.add_model_state(ModelState.from_model(Magazine)) rendered_state = project_state.render() self.assertEqual(len(rendered_state.get_models()), 3) # now make an invalid one with a ForeignKey project_state = ProjectState() project_state.add_model_state(ModelState.from_model(Book)) with self.assertRaises(ValueError): rendered_state = project_state.render() # and another with ManyToManyField project_state = ProjectState() project_state.add_model_state(ModelState.from_model(Magazine)) with self.assertRaises(ValueError): rendered_state = project_state.render()
def set_up_test_model(self): operations = [migrations.CreateModel( "Neighborhood", [ ("id", models.AutoField(primary_key=True)), ('name', models.CharField(max_length=100, unique=True)), ('geom', fields.MultiPolygonField(srid=4326)), ], )] return self.apply_operations('gis', ProjectState(), operations)