Fixed #30031 -- Added --no-header option to makemigrations/squashmigrations.

This commit is contained in:
Dakota Hawkins 2018-12-19 06:41:31 -05:00 committed by Carlton Gibson
parent b514dc14f4
commit 8d3147e130
6 changed files with 58 additions and 19 deletions

View File

@ -48,6 +48,10 @@ class Command(BaseCommand):
'-n', '--name',
help="Use this name for migration file(s).",
)
parser.add_argument(
'--no-header', action='store_false', dest='include_header',
help='Do not add header comments to new migration file(s).',
)
parser.add_argument(
'--check', action='store_true', dest='check_changes',
help='Exit with a non-zero status if model changes are missing migrations.',
@ -63,6 +67,7 @@ class Command(BaseCommand):
self.migration_name = options['name']
if self.migration_name and not self.migration_name.isidentifier():
raise CommandError('The migration name must be a valid Python identifier.')
self.include_header = options['include_header']
check_changes = options['check_changes']
# Make sure the app they asked for exists
@ -188,7 +193,7 @@ class Command(BaseCommand):
self.stdout.write(self.style.MIGRATE_HEADING("Migrations for '%s':" % app_label) + "\n")
for migration in app_migrations:
# Describe the migration
writer = MigrationWriter(migration)
writer = MigrationWriter(migration, self.include_header)
if self.verbosity >= 1:
# Display a relative path if it's below the current working
# directory, or an absolute path otherwise.
@ -288,7 +293,7 @@ class Command(BaseCommand):
self.migration_name or ("merge_%s" % get_migration_name_timestamp())
)
new_migration = subclass(migration_name, app_label)
writer = MigrationWriter(new_migration)
writer = MigrationWriter(new_migration, self.include_header)
if not self.dry_run:
# Write the merge migrations file to the disk

View File

@ -37,6 +37,10 @@ class Command(BaseCommand):
'--squashed-name',
help='Sets the name of the new squashed migration.',
)
parser.add_argument(
'--no-header', action='store_false', dest='include_header',
help='Do not add a header comment to the new squashed migration.',
)
def handle(self, **options):
@ -47,6 +51,7 @@ class Command(BaseCommand):
migration_name = options['migration_name']
no_optimize = options['no_optimize']
squashed_name = options['squashed_name']
include_header = options['include_header']
# Validate app_label.
try:
apps.get_app_config(app_label)
@ -178,7 +183,7 @@ class Command(BaseCommand):
new_migration.initial = True
# Write out the new migration file
writer = MigrationWriter(new_migration)
writer = MigrationWriter(new_migration, include_header)
with open(writer.path, "w", encoding='utf-8') as fh:
fh.write(writer.as_string())

View File

@ -132,8 +132,9 @@ class MigrationWriter:
of the migration file from it.
"""
def __init__(self, migration):
def __init__(self, migration, include_header=True):
self.migration = migration
self.include_header = include_header
self.needs_manual_porting = False
def as_string(self):
@ -195,10 +196,13 @@ class MigrationWriter:
if self.migration.replaces:
items['replaces_str'] = "\n replaces = %s\n" % self.serialize(self.migration.replaces)[0]
# Hinting that goes into comment
items.update(
version=get_version(),
timestamp=now().strftime("%Y-%m-%d %H:%M"),
)
if self.include_header:
items['migration_header'] = MIGRATION_HEADER_TEMPLATE % {
'version': get_version(),
'timestamp': now().strftime("%Y-%m-%d %H:%M"),
}
else:
items['migration_header'] = ""
if self.migration.initial:
items['initial_str'] = "\n initial = True\n"
@ -279,10 +283,14 @@ class MigrationWriter:
return serializer_factory(value).serialize()
MIGRATION_TEMPLATE = """\
MIGRATION_HEADER_TEMPLATE = """\
# Generated by Django %(version)s on %(timestamp)s
%(imports)s
"""
MIGRATION_TEMPLATE = """\
%(migration_header)s%(imports)s
class Migration(migrations.Migration):
%(replaces_str)s%(initial_str)s

View File

@ -776,6 +776,12 @@ Enables fixing of migration conflicts.
Allows naming the generated migration(s) instead of using a generated name. The
name must be a valid Python :ref:`identifier <python:identifiers>`.
.. django-admin-option:: --no-header
.. versionadded:: 2.2
Generate migration files without Django version and timestamp header.
.. django-admin-option:: --check
Makes ``makemigrations`` exit with a non-zero status when model changes without
@ -1156,6 +1162,12 @@ Suppresses all user prompts.
Sets the name of the squashed migration. When omitted, the name is based on the
first and last migration, with ``_squashed_`` in between.
.. django-admin-option:: --no-header
.. versionadded:: 2.2
Generate squashed migration file without Django version and timestamp header.
``startapp``
------------

View File

@ -194,6 +194,10 @@ Management Commands
* On Oracle, :djadmin:`dbshell` is wrapped with ``rlwrap``, if available.
``rlwrap`` provides a command history and editing of keyboard input.
* The new :option:`makemigrations --no-header` option avoids writing header
comments in generated migration file(s). This option is also available for
:djadmin:`squashmigrations`.
Migrations
~~~~~~~~~~

View File

@ -613,16 +613,21 @@ class WriterTests(SimpleTestCase):
})
dt = datetime.datetime(2015, 7, 31, 4, 40, 0, 0, tzinfo=utc)
with mock.patch('django.db.migrations.writer.now', lambda: dt):
writer = MigrationWriter(migration)
output = writer.as_string()
for include_header in (True, False):
with self.subTest(include_header=include_header):
writer = MigrationWriter(migration, include_header)
output = writer.as_string()
self.assertTrue(
output.startswith(
"# Generated by Django %(version)s on 2015-07-31 04:40\n" % {
'version': get_version(),
}
)
)
self.assertEqual(
include_header,
output.startswith(
"# Generated by Django %s on 2015-07-31 04:40\n\n" % get_version()
)
)
if not include_header:
# Make sure the output starts with something that's not
# a comment or indentation or blank line
self.assertRegex(output.splitlines(keepends=True)[0], r"^[^#\s]+")
def test_models_import_omitted(self):
"""