summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/migrations/operations/special.py15
-rw-r--r--docs/ref/migration-operations.txt16
-rw-r--r--docs/releases/1.8.txt5
-rw-r--r--tests/migrations/test_migrations_squashed_complex/1_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/2_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/3_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/3_squashed_5.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/4_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/5_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/6_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex/7_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py2
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/1_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/2_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py2
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/6_auto.py2
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/7_auto.py2
-rw-r--r--tests/migrations/test_operations.py20
25 files changed, 72 insertions, 26 deletions
diff --git a/django/db/migrations/operations/special.py b/django/db/migrations/operations/special.py
index 96fd2cc63c..00caa08684 100644
--- a/django/db/migrations/operations/special.py
+++ b/django/db/migrations/operations/special.py
@@ -61,6 +61,7 @@ class RunSQL(Operation):
Also accepts a list of operations that represent the state change effected
by this SQL change, in case it's custom column/table creation/deletion.
"""
+ noop = ''
def __init__(self, sql, reverse_sql=None, state_operations=None):
self.sql = sql
@@ -100,9 +101,9 @@ class RunSQL(Operation):
def describe(self):
return "Raw SQL operation"
- def _run_sql(self, schema_editor, sql):
- if isinstance(sql, (list, tuple)):
- for sql in sql:
+ def _run_sql(self, schema_editor, sqls):
+ if isinstance(sqls, (list, tuple)):
+ for sql in sqls:
params = None
if isinstance(sql, (list, tuple)):
elements = len(sql)
@@ -111,8 +112,8 @@ class RunSQL(Operation):
else:
raise ValueError("Expected a 2-tuple but got %d" % elements)
schema_editor.execute(sql, params=params)
- else:
- statements = schema_editor.connection.ops.prepare_sql_script(sql)
+ elif sqls != RunSQL.noop:
+ statements = schema_editor.connection.ops.prepare_sql_script(sqls)
for statement in statements:
schema_editor.execute(statement, params=None)
@@ -175,3 +176,7 @@ class RunPython(Operation):
def describe(self):
return "Raw Python operation"
+
+ @staticmethod
+ def noop(apps, schema_editor):
+ return None
diff --git a/docs/ref/migration-operations.txt b/docs/ref/migration-operations.txt
index 46b87f44c4..dcac7f26a6 100644
--- a/docs/ref/migration-operations.txt
+++ b/docs/ref/migration-operations.txt
@@ -245,6 +245,14 @@ operation that adds that field and so will try to run it again).
The ability to pass parameters to the ``sql`` and ``reverse_sql`` queries
was added.
+.. attribute:: RunSQL.noop
+
+ .. versionadded:: 1.8
+
+ Pass the ``RunSQL.noop`` attribute to ``sql`` or ``reverse_sql`` when you
+ want the operation not to do anything in the given direction. This is
+ especially useful in making the operation reversible.
+
.. _sqlparse: https://pypi.python.org/pypi/sqlparse
RunPython
@@ -321,6 +329,14 @@ set ``atomic=False``.
``schema_editor.connection.alias``, where ``schema_editor`` is the second
argument to your function).
+.. staticmethod:: RunPython.noop
+
+ .. versionadded:: 1.8
+
+ Pass the ``RunPython.noop`` method to ``code`` or ``reverse_code`` when
+ you want the operation not to do anything in the given direction. This is
+ especially useful in making the operation reversible.
+
SeparateDatabaseAndState
------------------------
diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt
index 3a522ee741..427ec5d493 100644
--- a/docs/releases/1.8.txt
+++ b/docs/releases/1.8.txt
@@ -457,6 +457,11 @@ Migrations
* A :ref:`generic mechanism to handle the deprecation of model fields
<migrations-removing-model-fields>` was added.
+* The :attr:`RunPython.noop <django.db.migrations.operations.RunPython.noop>`
+ and :meth:`RunSQL.noop() <django.db.migrations.operations.RunSQL.noop>` class
+ attribute/method were added to ease in making ``RunPython`` and ``RunSQL``
+ operations reversible.
+
Models
^^^^^^
diff --git a/tests/migrations/test_migrations_squashed_complex/1_auto.py b/tests/migrations/test_migrations_squashed_complex/1_auto.py
index 25edcfa290..bf12688063 100644
--- a/tests/migrations/test_migrations_squashed_complex/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/1_auto.py
@@ -7,5 +7,5 @@ from django.db import migrations
class Migration(migrations.Migration):
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/2_auto.py b/tests/migrations/test_migrations_squashed_complex/2_auto.py
index 9107c35868..1d952ad0df 100644
--- a/tests/migrations/test_migrations_squashed_complex/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/2_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "1_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/3_auto.py b/tests/migrations/test_migrations_squashed_complex/3_auto.py
index 98e679fc12..d780968115 100644
--- a/tests/migrations/test_migrations_squashed_complex/3_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/3_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py b/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py
index ac1bcdee6d..f7dde03524 100644
--- a/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py
+++ b/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py
@@ -15,5 +15,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/4_auto.py b/tests/migrations/test_migrations_squashed_complex/4_auto.py
index 8fab746542..c39b16e454 100644
--- a/tests/migrations/test_migrations_squashed_complex/4_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/4_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "3_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/5_auto.py b/tests/migrations/test_migrations_squashed_complex/5_auto.py
index 5dda63aae5..754fe2d253 100644
--- a/tests/migrations/test_migrations_squashed_complex/5_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/5_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "4_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/6_auto.py b/tests/migrations/test_migrations_squashed_complex/6_auto.py
index 5ca558bc3b..65d829cd32 100644
--- a/tests/migrations/test_migrations_squashed_complex/6_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/6_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "5_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex/7_auto.py b/tests/migrations/test_migrations_squashed_complex/7_auto.py
index e9f5533364..f1b3cd3e49 100644
--- a/tests/migrations/test_migrations_squashed_complex/7_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/7_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "6_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py
index 25edcfa290..bf12688063 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py
@@ -7,5 +7,5 @@ from django.db import migrations
class Migration(migrations.Migration):
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py
index dcd67ca101..13a844275b 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py
index d74691fe44..521e70f5d2 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py
@@ -14,5 +14,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto"), ("app2", "2_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py
index f2b64db833..aa0e86e560 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "2_auto"), ("app2", "2_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py
index fa36f18566..145e495a18 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "3_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py
index dcd67ca101..13a844275b 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py
index fcd43bd0c6..6ef4dba71e 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py
@@ -14,5 +14,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py
index 9743fc92a2..35fc7b8c1c 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app2", "1_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/1_auto.py b/tests/migrations/test_migrations_squashed_erroneous/1_auto.py
index 25edcfa290..bf12688063 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/1_auto.py
@@ -7,5 +7,5 @@ from django.db import migrations
class Migration(migrations.Migration):
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/2_auto.py b/tests/migrations/test_migrations_squashed_erroneous/2_auto.py
index 9107c35868..1d952ad0df 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/2_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "1_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py b/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py
index ac1bcdee6d..f7dde03524 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py
@@ -15,5 +15,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/6_auto.py b/tests/migrations/test_migrations_squashed_erroneous/6_auto.py
index 5ca558bc3b..65d829cd32 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/6_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/6_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "5_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/7_auto.py b/tests/migrations/test_migrations_squashed_erroneous/7_auto.py
index e9f5533364..f1b3cd3e49 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/7_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/7_auto.py
@@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "6_auto")]
operations = [
- migrations.RunPython(lambda apps, schema_editor: None)
+ migrations.RunPython(migrations.RunPython.noop)
]
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 90ec456f84..f3e33b0f7e 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -1494,6 +1494,15 @@ class OperationTests(OperationTestBase):
operation.database_backwards,
"test_runsql", editor, new_state, project_state)
+ def test_run_sql_noop(self):
+ """
+ #24098 - Tests no-op RunSQL operations.
+ """
+ operation = migrations.RunSQL(migrations.RunSQL.noop, migrations.RunSQL.noop)
+ with connection.schema_editor() as editor:
+ operation.database_forwards("test_runsql", editor, None, None)
+ operation.database_backwards("test_runsql", editor, None, None)
+
def test_run_python(self):
"""
Tests the RunPython operation
@@ -1620,6 +1629,17 @@ class OperationTests(OperationTestBase):
self.assertEqual(definition[1], [])
self.assertEqual(sorted(definition[2]), ["atomic", "code"])
+ def test_run_python_noop(self):
+ """
+ #24098 - Tests no-op RunPython operations.
+ """
+ project_state = ProjectState()
+ new_state = project_state.clone()
+ operation = migrations.RunPython(migrations.RunPython.noop, migrations.RunPython.noop)
+ with connection.schema_editor() as editor:
+ operation.database_forwards("test_runpython", editor, project_state, new_state)
+ operation.database_backwards("test_runpython", editor, new_state, project_state)
+
@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
def test_separate_database_and_state(self):
"""