1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

Fixed #31700 -- Made makemigrations command display meaningful symbols for each operation.

This commit is contained in:
Amir Karimi
2023-09-16 05:41:22 +03:30
committed by Mariusz Felisiak
parent c7e986fc9f
commit 27a3eee721
14 changed files with 214 additions and 19 deletions

View File

@@ -5,12 +5,13 @@ from django.contrib.postgres.signals import (
)
from django.db import NotSupportedError, router
from django.db.migrations import AddConstraint, AddIndex, RemoveIndex
from django.db.migrations.operations.base import Operation
from django.db.migrations.operations.base import Operation, OperationCategory
from django.db.models.constraints import CheckConstraint
class CreateExtension(Operation):
reversible = True
category = OperationCategory.ADDITION
def __init__(self, name):
self.name = name
@@ -120,6 +121,7 @@ class AddIndexConcurrently(NotInTransactionMixin, AddIndex):
"""Create an index using PostgreSQL's CREATE INDEX CONCURRENTLY syntax."""
atomic = False
category = OperationCategory.ADDITION
def describe(self):
return "Concurrently create index %s on field(s) %s of model %s" % (
@@ -145,6 +147,7 @@ class RemoveIndexConcurrently(NotInTransactionMixin, RemoveIndex):
"""Remove an index using PostgreSQL's DROP INDEX CONCURRENTLY syntax."""
atomic = False
category = OperationCategory.REMOVAL
def describe(self):
return "Concurrently remove index %s from %s" % (self.name, self.model_name)
@@ -213,6 +216,8 @@ class CollationOperation(Operation):
class CreateCollation(CollationOperation):
"""Create a collation."""
category = OperationCategory.ADDITION
def database_forwards(self, app_label, schema_editor, from_state, to_state):
if schema_editor.connection.vendor != "postgresql" or not router.allow_migrate(
schema_editor.connection.alias, app_label
@@ -236,6 +241,8 @@ class CreateCollation(CollationOperation):
class RemoveCollation(CollationOperation):
"""Remove a collation."""
category = OperationCategory.REMOVAL
def database_forwards(self, app_label, schema_editor, from_state, to_state):
if schema_editor.connection.vendor != "postgresql" or not router.allow_migrate(
schema_editor.connection.alias, app_label
@@ -262,6 +269,8 @@ class AddConstraintNotValid(AddConstraint):
NOT VALID syntax.
"""
category = OperationCategory.ADDITION
def __init__(self, model_name, constraint):
if not isinstance(constraint, CheckConstraint):
raise TypeError(
@@ -293,6 +302,8 @@ class AddConstraintNotValid(AddConstraint):
class ValidateConstraint(Operation):
"""Validate a table NOT VALID constraint."""
category = OperationCategory.ALTERATION
def __init__(self, model_name, name):
self.model_name = model_name
self.name = name

View File

@@ -348,7 +348,7 @@ class Command(BaseCommand):
migration_string = self.get_relative_path(writer.path)
self.log(" %s\n" % self.style.MIGRATE_LABEL(migration_string))
for operation in migration.operations:
self.log(" - %s" % operation.describe())
self.log(" %s" % operation.formatted_description())
if self.scriptable:
self.stdout.write(migration_string)
if not self.dry_run:
@@ -456,7 +456,7 @@ class Command(BaseCommand):
for migration in merge_migrations:
self.log(self.style.MIGRATE_LABEL(" Branch %s" % migration.name))
for operation in migration.merged_operations:
self.log(" - %s" % operation.describe())
self.log(" %s" % operation.formatted_description())
if questioner.ask_merge(app_label):
# If they still want to merge it, then write out an empty
# file depending on the migrations needing merging.

View File

@@ -1,6 +1,17 @@
import enum
from django.db import router
class OperationCategory(str, enum.Enum):
ADDITION = "+"
REMOVAL = "-"
ALTERATION = "~"
PYTHON = "p"
SQL = "s"
MIXED = "?"
class Operation:
"""
Base class for migration operations.
@@ -33,6 +44,8 @@ class Operation:
serialization_expand_args = []
category = None
def __new__(cls, *args, **kwargs):
# We capture the arguments to make returning them trivial
self = object.__new__(cls)
@@ -85,6 +98,13 @@ class Operation:
"""
return "%s: %s" % (self.__class__.__name__, self._constructor_args)
def formatted_description(self):
"""Output a description prefixed by a category symbol."""
description = self.describe()
if self.category is None:
return f"{OperationCategory.MIXED.value} {description}"
return f"{self.category.value} {description}"
@property
def migration_name_fragment(self):
"""

View File

@@ -2,7 +2,7 @@ from django.db.migrations.utils import field_references
from django.db.models import NOT_PROVIDED
from django.utils.functional import cached_property
from .base import Operation
from .base import Operation, OperationCategory
class FieldOperation(Operation):
@@ -75,6 +75,8 @@ class FieldOperation(Operation):
class AddField(FieldOperation):
"""Add a field to a model."""
category = OperationCategory.ADDITION
def __init__(self, model_name, name, field, preserve_default=True):
self.preserve_default = preserve_default
super().__init__(model_name, name, field)
@@ -154,6 +156,8 @@ class AddField(FieldOperation):
class RemoveField(FieldOperation):
"""Remove a field from a model."""
category = OperationCategory.REMOVAL
def deconstruct(self):
kwargs = {
"model_name": self.model_name,
@@ -201,6 +205,8 @@ class AlterField(FieldOperation):
new field.
"""
category = OperationCategory.ALTERATION
def __init__(self, model_name, name, field, preserve_default=True):
self.preserve_default = preserve_default
super().__init__(model_name, name, field)
@@ -270,6 +276,8 @@ class AlterField(FieldOperation):
class RenameField(FieldOperation):
"""Rename a field on the model. Might affect db_column too."""
category = OperationCategory.ALTERATION
def __init__(self, model_name, old_name, new_name):
self.old_name = old_name
self.new_name = new_name

View File

@@ -1,5 +1,5 @@
from django.db import models
from django.db.migrations.operations.base import Operation
from django.db.migrations.operations.base import Operation, OperationCategory
from django.db.migrations.state import ModelState
from django.db.migrations.utils import field_references, resolve_relation
from django.db.models.options import normalize_together
@@ -41,6 +41,7 @@ class ModelOperation(Operation):
class CreateModel(ModelOperation):
"""Create a model's table."""
category = OperationCategory.ADDITION
serialization_expand_args = ["fields", "options", "managers"]
def __init__(self, name, fields, options=None, bases=None, managers=None):
@@ -347,6 +348,8 @@ class CreateModel(ModelOperation):
class DeleteModel(ModelOperation):
"""Drop a model's table."""
category = OperationCategory.REMOVAL
def deconstruct(self):
kwargs = {
"name": self.name,
@@ -382,6 +385,8 @@ class DeleteModel(ModelOperation):
class RenameModel(ModelOperation):
"""Rename a model."""
category = OperationCategory.ALTERATION
def __init__(self, old_name, new_name):
self.old_name = old_name
self.new_name = new_name
@@ -499,6 +504,8 @@ class RenameModel(ModelOperation):
class ModelOptionOperation(ModelOperation):
category = OperationCategory.ALTERATION
def reduce(self, operation, app_label):
if (
isinstance(operation, (self.__class__, DeleteModel))
@@ -849,6 +856,8 @@ class IndexOperation(Operation):
class AddIndex(IndexOperation):
"""Add an index on a model."""
category = OperationCategory.ADDITION
def __init__(self, model_name, index):
self.model_name = model_name
if not index.name:
@@ -911,6 +920,8 @@ class AddIndex(IndexOperation):
class RemoveIndex(IndexOperation):
"""Remove an index from a model."""
category = OperationCategory.REMOVAL
def __init__(self, model_name, name):
self.model_name = model_name
self.name = name
@@ -954,6 +965,8 @@ class RemoveIndex(IndexOperation):
class RenameIndex(IndexOperation):
"""Rename an index."""
category = OperationCategory.ALTERATION
def __init__(self, model_name, new_name, old_name=None, old_fields=None):
if not old_name and not old_fields:
raise ValueError(
@@ -1104,6 +1117,7 @@ class RenameIndex(IndexOperation):
class AddConstraint(IndexOperation):
category = OperationCategory.ADDITION
option_name = "constraints"
def __init__(self, model_name, constraint):
@@ -1154,6 +1168,7 @@ class AddConstraint(IndexOperation):
class RemoveConstraint(IndexOperation):
category = OperationCategory.REMOVAL
option_name = "constraints"
def __init__(self, model_name, name):

View File

@@ -1,6 +1,6 @@
from django.db import router
from .base import Operation
from .base import Operation, OperationCategory
class SeparateDatabaseAndState(Operation):
@@ -11,6 +11,7 @@ class SeparateDatabaseAndState(Operation):
that affect the state or not the database, or so on.
"""
category = OperationCategory.MIXED
serialization_expand_args = ["database_operations", "state_operations"]
def __init__(self, database_operations=None, state_operations=None):
@@ -68,6 +69,7 @@ class RunSQL(Operation):
by this SQL change, in case it's custom column/table creation/deletion.
"""
category = OperationCategory.SQL
noop = ""
def __init__(
@@ -138,6 +140,7 @@ class RunPython(Operation):
Run Python code in a context suitable for doing versioned ORM operations.
"""
category = OperationCategory.PYTHON
reduces_to_sql = False
def __init__(