Exemplo n.º 1
0
 def test_pre_deploy_operations(self):
     pre_deploy_operation = Operation()
     pre_deploy_operation.stage = Stage.PRE_DEPLOY
     operations = [CreateModel("model", []), pre_deploy_operation]
     for operation in operations:
         with self.subTest(operation=operation):
             self.assertIs(get_operation_stage(operation), Stage.PRE_DEPLOY)
Exemplo n.º 2
0
class Migration(BaseMigration):
    """Represents initial migration."""

    initial: bool = True
    dependencies: List[str] = []
    operations: List[CreateModel] = [
        CreateModel(
            name="Quote",
            fields=[
                (
                    "id",
                    AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("quote", TextField()),
                ("author", CharField(max_length=100)),
                ("source", URLField(blank=True, null=True)),
                ["cover", URLField(blank=True, null=True)],
                ("added", DateTimeField(auto_now_add=True)),
                ("edited", DateTimeField(auto_now=True)),
            ],
            options={"ordering": ["-added"]},
        ),
    ]
Exemplo n.º 3
0
 def reduce_create_model_add_field(self, operation, other, in_between):
     if operation.name_lower == other.model_name_lower:
         # Don't allow optimizations of FKs through models they reference
         if hasattr(other.field,
                    "remote_field") and other.field.remote_field:
             for between in in_between:
                 # Check that it doesn't point to the model
                 app_label, object_name = self.model_to_key(
                     other.field.remote_field.model)
                 if between.references_model(object_name, app_label):
                     return None
                 # Check that it's not through the model
                 if getattr(other.field.remote_field, "through", None):
                     app_label, object_name = self.model_to_key(
                         other.field.remote_field.through)
                     if between.references_model(object_name, app_label):
                         return None
         # OK, that's fine
         return [
             CreateModel(
                 operation.name,
                 fields=operation.fields + [(other.name, other.field)],
                 options=operation.options,
                 bases=operation.bases,
                 managers=operation.managers,
             )
         ]
def test_unique_index_migrations():
    index = UniqueIndex(fields=["name", "other_name"], name="index1")

    ops = [
        CreateModel(
            name="mymodel",
            fields=[
                ("name", models.TextField()),
                ("other_name", models.TextField()),
            ],
            options={
                # "indexes": [index],
            },
        ),
        AddIndex(model_name="mymodel", index=index),
    ]

    with filtered_schema_editor("CREATE UNIQUE INDEX") as calls:
        apply_migration(ops)

    calls = [call[0] for _, call, _ in calls["CREATE UNIQUE INDEX"]]

    db_table = "tests_mymodel"
    query = 'CREATE UNIQUE INDEX "index1" ON "{0}" ("name", "other_name")'
    assert str(calls[0]) == query.format(db_table)
Exemplo n.º 5
0
def test_ciui_migrations():
    """Tests whether migrations for case sensitive indexes are being created as
    expected."""

    index_1 = CaseInsensitiveUniqueIndex(
        fields=["name", "other_name"], name="index1"
    )

    ops = [
        CreateModel(
            name="mymodel",
            fields=[
                ("name", models.CharField(max_length=255)),
                ("other_name", models.CharField(max_length=255)),
            ],
        ),
        AddIndex(model_name="mymodel", index=index_1),
    ]

    with filtered_schema_editor("CREATE UNIQUE INDEX") as calls:
        apply_migration(ops)

    sql = str([call[0] for _, call, _ in calls["CREATE UNIQUE INDEX"]][0])
    expected_sql = 'CREATE UNIQUE INDEX "index1" ON "tests_mymodel" (LOWER("name"), LOWER("other_name"))'
    assert sql == expected_sql
Exemplo n.º 6
0
 def test_ambiguous_operations(self):
     self.migration.operations = [
         CreateModel("model", []),
         DeleteModel("model")
     ]
     with self.assertRaises(AmbiguousStage):
         must_post_deploy_migration(self.migration)
Exemplo n.º 7
0
 def test_ambiguous_operations(self):
     self.migration.operations = [
         CreateModel("model", []),
         DeleteModel("model")
     ]
     with self.assertRaises(AmbiguousStage):
         get_migration_stage(self.migration)
Exemplo n.º 8
0
 def reduce_create_model_remove_field(self, operation, other, in_between):
     if operation.name_lower == other.model_name_lower:
         return [
             CreateModel(
                 operation.name,
                 fields=[(n, v) for n, v in operation.fields
                         if n.lower() != other.name_lower],
                 options=operation.options,
                 bases=operation.bases,
                 managers=operation.managers,
             )
         ]
Exemplo n.º 9
0
    def test_operations_stages(self):
        self.assertIsNone(get_migration_stage(self.migration))

        self.migration.operations = [CreateModel("model", [])]
        self.assertEqual(get_migration_stage(self.migration), Stage.PRE_DEPLOY)

        self.migration.operations = [
            DeleteModel("model"),
            RemoveField("model", "field"),
        ]
        self.assertEqual(get_migration_stage(self.migration),
                         Stage.POST_DEPLOY)
Exemplo n.º 10
0
    def add_create_view_model(self, model: Model, operation: CreateModel):
        """Adds a :see:PostgresCreateViewModel operation to the list of
        operations to execute in the migration."""

        view_options = model._view_meta.original_attrs
        _, args, kwargs = operation.deconstruct()

        self.add(
            operations.PostgresCreateViewModel(
                *args, **kwargs, view_options=view_options
            )
        )
Exemplo n.º 11
0
 def reduce_create_model_rename_field(self, operation, other, in_between):
     if operation.name_lower == other.model_name_lower:
         return [
             CreateModel(
                 operation.name,
                 fields=[(other.new_name if n == other.old_name else n, v)
                         for n, v in operation.fields],
                 options=operation.options,
                 bases=operation.bases,
                 managers=operation.managers,
             )
         ]
Exemplo n.º 12
0
    def test_stage_fallback_setting(self):
        self.migration.operations = [
            CreateModel("model", []),
            DeleteModel("model")
        ]
        with self.assertRaises(AmbiguousStage):
            get_migration_stage(self.migration)

        overrides = ["tests.migration", "tests"]
        for stage, override in product(Stage, overrides):
            with self.subTest(stage=stage, override=override), self.settings(
                    MIGRATION_STAGES_FALLBACK={override: stage}):
                self.assertIs(get_migration_stage(self.migration), stage)
    def add_delete_model(self, operation: CreateModel):
        """Adds the specified :see:Deletemodel operation to the list of
        operations to execute in the migration."""

        model = self.autodetector.old_apps.get_model(self.app_label,
                                                     operation.name)
        if not issubclass(model, PostgresPartitionedModel):
            return self.add(operation)

        _, args, kwargs = operation.deconstruct()

        return self.add(
            operations.PostgresDeletePartitionedModel(*args, **kwargs))
Exemplo n.º 14
0
 def reduce_create_model_rename_model(self, operation, other, in_between):
     """
     Folds a model rename into its create
     """
     if operation.name_lower == other.old_name_lower:
         return [
             CreateModel(
                 other.new_name,
                 fields=operation.fields,
                 options=operation.options,
                 bases=operation.bases,
                 managers=operation.managers,
             )
         ]
Exemplo n.º 15
0
class PartitionOperationsTests(SimpleTestCase):
    pre_deploy_operations = [
        CreateModel("model", []),
    ]
    post_deploy_operations = [
        DeleteModel("model"),
    ]

    def test_empty(self):
        self.assertEqual(partition_operations([], "migrations"), ([], []))

    def test_pre_deploy_only(self):
        self.assertEqual(
            partition_operations(self.pre_deploy_operations, "migrations"),
            (self.pre_deploy_operations, []),
        )

    def test_post_deploy_only(self):
        self.assertEqual(
            partition_operations(self.post_deploy_operations, "migrations"),
            ([], self.post_deploy_operations),
        )

    def test_mixed(self):
        self.assertEqual(
            partition_operations(
                self.pre_deploy_operations + self.post_deploy_operations,
                "migrations"),
            (self.pre_deploy_operations, self.post_deploy_operations),
        )

    def test_mixed_reorder(self):
        post_deploy_operations = [DeleteModel("other")]
        self.assertEqual(
            partition_operations(
                post_deploy_operations + self.pre_deploy_operations,
                "migrations"),
            (self.pre_deploy_operations, post_deploy_operations),
        )

    def test_ambiguous(self):
        with self.assertRaises(AmbiguousStage):
            partition_operations(
                self.post_deploy_operations + self.pre_deploy_operations,
                "migrations")
Exemplo n.º 16
0
    def add_create_materialized_view_model(self, operation: CreateModel):
        """Adds a :see:PostgresCreateMaterializedViewModel operation to the
        list of operations to execute in the migration."""

        if django.VERSION >= (4, 0):
            model_state = self.autodetector.to_state.models[
                self.app_label, operation.name.lower()]
            view_options = model_state.view_options
        else:
            model = self.autodetector.new_apps.get_model(
                self.app_label, operation.name)
            view_options = model._view_meta.original_attrs

        _, args, kwargs = operation.deconstruct()

        self.add(
            operations.PostgresCreateMaterializedViewModel(
                *args, **kwargs, view_options=view_options))
    def add_create_model(self, operation: CreateModel):
        """Adds the specified :see:CreateModel operation to the list of
        operations to execute in the migration."""

        model = self.autodetector.new_apps.get_model(self.app_label,
                                                     operation.name)
        if not issubclass(model, PostgresPartitionedModel):
            return self.add(operation)

        partitioning_options = model._partitioning_meta.original_attrs
        _, args, kwargs = operation.deconstruct()

        self.add(
            operations.PostgresAddDefaultPartition(model_name=model.__name__,
                                                   name="default"))

        self.add(
            operations.PostgresCreatePartitionedModel(
                *args, **kwargs, partitioning_options=partitioning_options))
Exemplo n.º 18
0
    def add_create_partitioned_model(
        self, model: Model, operation: CreateModel
    ):
        """Adds a :see:PostgresCreatePartitionedModel operation to the list of
        operations to execute in the migration."""

        partitioning_options = model._partitioning_meta.original_attrs
        _, args, kwargs = operation.deconstruct()

        self.add(
            operations.PostgresAddDefaultPartition(
                model_name=model.__name__, name="default"
            )
        )

        self.add(
            operations.PostgresCreatePartitionedModel(
                *args, **kwargs, partitioning_options=partitioning_options
            )
        )
def test_cui_migrations():
    """Tests whether the migrations are properly generated and executed."""

    index_1 = ConditionalUniqueIndex(
        fields=["name", "other_name"],
        condition='"name" IS NOT NULL',
        name="index1",
    )

    index_2 = ConditionalUniqueIndex(fields=["other_name"],
                                     condition='"name" IS NULL',
                                     name="index2")

    ops = [
        CreateModel(
            name="mymodel",
            fields=[
                ("id", models.IntegerField(primary_key=True)),
                ("name", models.CharField(max_length=255, null=True)),
                ("other_name", models.CharField(max_length=255)),
            ],
            options={
                # "indexes": [index_1, index_2],
            },
        ),
        AddIndex(model_name="mymodel", index=index_1),
        AddIndex(model_name="mymodel", index=index_2),
    ]

    with filtered_schema_editor("CREATE UNIQUE INDEX") as calls:
        apply_migration(ops)

    calls = [call[0] for _, call, _ in calls["CREATE UNIQUE INDEX"]]

    db_table = "tests_mymodel"
    query = 'CREATE UNIQUE INDEX "index1" ON "{0}" ("name", "other_name") WHERE "name" IS NOT NULL'
    assert str(calls[0]) == query.format(db_table)

    query = 'CREATE UNIQUE INDEX "index2" ON "{0}" ("other_name") WHERE "name" IS NULL'
    assert str(calls[1]) == query.format(db_table)
Exemplo n.º 20
0
    def add_create_partitioned_model(self, operation: CreateModel):
        """Adds a :see:PostgresCreatePartitionedModel operation to the list of
        operations to execute in the migration."""

        if django.VERSION >= (4, 0):
            model_state = self.autodetector.to_state.models[
                self.app_label, operation.name.lower()]
            partitioning_options = model_state.partitioning_options
        else:
            model = self.autodetector.new_apps.get_model(
                self.app_label, operation.name)
            partitioning_options = model._partitioning_meta.original_attrs

        _, args, kwargs = operation.deconstruct()

        if partitioning_options["method"] != PostgresPartitioningMethod.HASH:
            self.add(
                operations.PostgresAddDefaultPartition(
                    model_name=operation.name, name="default"))

        self.add(
            operations.PostgresCreatePartitionedModel(
                *args, **kwargs, partitioning_options=partitioning_options))