1
0
mirror of https://github.com/django/django.git synced 2025-06-05 11:39:13 +00:00
This commit is contained in:
Clinton Christian 2024-06-15 03:14:59 -04:00
parent 6efbeb997c
commit 2a7cb57a7e
No known key found for this signature in database
GPG Key ID: E1BC7B3DEA3DC2C9
3 changed files with 70 additions and 1 deletions

View File

@ -5,12 +5,13 @@ from django.apps import apps
from django.conf import settings from django.conf import settings
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.core.management.utils import run_formatters from django.core.management.utils import run_formatters
from django.db import DEFAULT_DB_ALIAS, connections, migrations from django.db import DEFAULT_DB_ALIAS, connections, migrations, models
from django.db.migrations.loader import AmbiguityError, MigrationLoader from django.db.migrations.loader import AmbiguityError, MigrationLoader
from django.db.migrations.migration import SwappableTuple from django.db.migrations.migration import SwappableTuple
from django.db.migrations.optimizer import MigrationOptimizer from django.db.migrations.optimizer import MigrationOptimizer
from django.db.migrations.writer import MigrationWriter from django.db.migrations.writer import MigrationWriter
from django.utils.version import get_docs_version from django.utils.version import get_docs_version
from django.db.migrations.operations.base import OperationCategory
class Command(BaseCommand): class Command(BaseCommand):
@ -36,6 +37,14 @@ class Command(BaseCommand):
"migration_name", "migration_name",
help="Migrations will be squashed until and including this migration.", help="Migrations will be squashed until and including this migration.",
) )
parser.add_argument(
"--ignore-dependencies",
"--ignore-deps",
action="store_false",
dest="ignore_dependencies",
help="Ignore dependencies, except for those included in the"
" initial migration.",
)
parser.add_argument( parser.add_argument(
"--no-optimize", "--no-optimize",
action="store_true", action="store_true",
@ -65,6 +74,7 @@ class Command(BaseCommand):
app_label = options["app_label"] app_label = options["app_label"]
start_migration_name = options["start_migration_name"] start_migration_name = options["start_migration_name"]
migration_name = options["migration_name"] migration_name = options["migration_name"]
ignore_dependencies = options["ignore_dependencies"]
no_optimize = options["no_optimize"] no_optimize = options["no_optimize"]
squashed_name = options["squashed_name"] squashed_name = options["squashed_name"]
include_header = options["include_header"] include_header = options["include_header"]
@ -140,6 +150,12 @@ class Command(BaseCommand):
# We need to take all dependencies from the first migration in the list # We need to take all dependencies from the first migration in the list
# as it may be 0002 depending on 0001 # as it may be 0002 depending on 0001
first_migration = True first_migration = True
ignore_restricted_categories = set([
OperationCategory.ADDITION,
OperationCategory.ALTERATION
])
for smigration in migrations_to_squash: for smigration in migrations_to_squash:
if smigration.replaces: if smigration.replaces:
raise CommandError( raise CommandError(
@ -147,7 +163,24 @@ class Command(BaseCommand):
"normal migration first: https://docs.djangoproject.com/en/%s/" "normal migration first: https://docs.djangoproject.com/en/%s/"
"topics/migrations/#squashing-migrations" % get_docs_version() "topics/migrations/#squashing-migrations" % get_docs_version()
) )
if not first_migration and ignore_dependencies:
filtered_operations = []
for operation in smigration.operations:
if (operation.category in ignore_restricted_categories
and isinstance(operation.field, models.fields.related.RelatedField)):
#and operation field app_label != app_label:
continue
filtered_operations.append(operation)
operations.extend(filtered_operations)
continue
operations.extend(smigration.operations) operations.extend(smigration.operations)
for dependency in smigration.dependencies: for dependency in smigration.dependencies:
if isinstance(dependency, SwappableTuple): if isinstance(dependency, SwappableTuple):
if settings.AUTH_USER_MODEL == dependency.setting: if settings.AUTH_USER_MODEL == dependency.setting:
@ -156,6 +189,7 @@ class Command(BaseCommand):
dependencies.add(dependency) dependencies.add(dependency)
elif dependency[0] != smigration.app_label or first_migration: elif dependency[0] != smigration.app_label or first_migration:
dependencies.add(dependency) dependencies.add(dependency)
first_migration = False first_migration = False
if no_optimize: if no_optimize:

View File

@ -0,0 +1,16 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("author_app", "0001_initial"),
("book_app", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="Book",
name="author2",
field=models.ForeignKey("author_app.Author", models.CASCADE),
),
]

View File

@ -3044,6 +3044,25 @@ class SquashMigrationsTests(MigrationTestBase):
+ black_warning, + black_warning,
) )
@override_settings(
INSTALLED_APPS=[
"migrations.migrations_test_apps.alter_fk.author_app",
"migrations.migrations_test_apps.alter_fk.book_app",
]
)
def test_squashmigrations_ignore_dependencies_alter_relation_multi_apps(self):
with self.temporary_migration_module(
module="migrations.migrations_test_apps.alter_fk.book_app"):
call_command(
"squashmigrations",
"book_app",
"0001",
"0002",
interactive=False,
ignore_dependencies=True,
verbosity=0,
)
class AppLabelErrorTests(TestCase): class AppLabelErrorTests(TestCase):
""" """