예제 #1
0
    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()
예제 #2
0
    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)
예제 #3
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
예제 #4
0
    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,
        )
예제 #5
0
    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')
예제 #6
0
    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")
예제 #7
0
 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"})
예제 #8
0
    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])
예제 #9
0
    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")
예제 #10
0
    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)
예제 #11
0
    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)
예제 #12
0
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
예제 #13
0
    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)
예제 #14
0
 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)
예제 #15
0
 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)
예제 #16
0
    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)
예제 #17
0
    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)
예제 #18
0
파일: test_state.py 프로젝트: zejn/django
    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)
예제 #19
0
파일: django.py 프로젝트: zvrr/sentry
 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)
예제 #20
0
    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())
예제 #22
0
 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'})
예제 #23
0
 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,
         })
예제 #24
0
 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")
예제 #25
0
 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")
예제 #26
0
 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)
예제 #27
0
 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
예제 #28
0
파일: test_state.py 프로젝트: rsvip/Django
    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
예제 #29
0
    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()
예제 #30
0
 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)