summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorLoic Bistuer <loic.bistuer@gmail.com>2015-01-09 00:10:10 +0700
committerLoic Bistuer <loic.bistuer@gmail.com>2015-01-10 00:30:48 +0700
commit8f4877c89d0f28e289399fbb46357623a49e7eb0 (patch)
tree928a44b6cdef3f685f80f350af554e1252e9b136 /django
parent665e0aa6ec80a48492033a3b2b4ffdfaae3c78eb (diff)
Fixed #22583 -- Allowed RunPython and RunSQL to provide hints to the db router.
Thanks Markus Holtermann and Tim Graham for the review.
Diffstat (limited to 'django')
-rw-r--r--django/db/migrations/operations/base.py16
-rw-r--r--django/db/migrations/operations/special.py30
-rw-r--r--django/db/utils.py4
3 files changed, 29 insertions, 21 deletions
diff --git a/django/db/migrations/operations/base.py b/django/db/migrations/operations/base.py
index 655f03a4c6..04089938c2 100644
--- a/django/db/migrations/operations/base.py
+++ b/django/db/migrations/operations/base.py
@@ -98,17 +98,15 @@ class Operation(object):
"""
return self.references_model(model_name, app_label)
- def allowed_to_migrate(self, connection_alias, model):
+ def allowed_to_migrate(self, connection_alias, model, hints=None):
"""
- Returns if we're allowed to migrate the model. Checks the router,
- if it's a proxy, if it's managed, and if it's swapped out.
+ Returns if we're allowed to migrate the model.
"""
- return (
- not model._meta.proxy and
- not model._meta.swapped and
- model._meta.managed and
- router.allow_migrate(connection_alias, model)
- )
+ # Always skip if proxy, swapped out, or unmanaged.
+ if model and (model._meta.proxy or model._meta.swapped or not model._meta.managed):
+ return False
+
+ return router.allow_migrate(connection_alias, model, **(hints or {}))
def __repr__(self):
return "<%s %s%s>" % (
diff --git a/django/db/migrations/operations/special.py b/django/db/migrations/operations/special.py
index 00caa08684..91261f724f 100644
--- a/django/db/migrations/operations/special.py
+++ b/django/db/migrations/operations/special.py
@@ -63,10 +63,11 @@ class RunSQL(Operation):
"""
noop = ''
- def __init__(self, sql, reverse_sql=None, state_operations=None):
+ def __init__(self, sql, reverse_sql=None, state_operations=None, hints=None):
self.sql = sql
self.reverse_sql = reverse_sql
self.state_operations = state_operations or []
+ self.hints = hints or {}
def deconstruct(self):
kwargs = {
@@ -76,6 +77,8 @@ class RunSQL(Operation):
kwargs['reverse_sql'] = self.reverse_sql
if self.state_operations:
kwargs['state_operations'] = self.state_operations
+ if self.hints:
+ kwargs['hints'] = self.hints
return (
self.__class__.__name__,
[],
@@ -91,12 +94,14 @@ class RunSQL(Operation):
state_operation.state_forwards(app_label, state)
def database_forwards(self, app_label, schema_editor, from_state, to_state):
- self._run_sql(schema_editor, self.sql)
+ if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints):
+ self._run_sql(schema_editor, self.sql)
def database_backwards(self, app_label, schema_editor, from_state, to_state):
if self.reverse_sql is None:
raise NotImplementedError("You cannot reverse this operation")
- self._run_sql(schema_editor, self.reverse_sql)
+ if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints):
+ self._run_sql(schema_editor, self.reverse_sql)
def describe(self):
return "Raw SQL operation"
@@ -125,7 +130,7 @@ class RunPython(Operation):
reduces_to_sql = False
- def __init__(self, code, reverse_code=None, atomic=True):
+ def __init__(self, code, reverse_code=None, atomic=True, hints=None):
self.atomic = atomic
# Forwards code
if not callable(code):
@@ -138,6 +143,7 @@ class RunPython(Operation):
if not callable(reverse_code):
raise ValueError("RunPython must be supplied with callable arguments")
self.reverse_code = reverse_code
+ self.hints = hints or {}
def deconstruct(self):
kwargs = {
@@ -147,6 +153,8 @@ class RunPython(Operation):
kwargs['reverse_code'] = self.reverse_code
if self.atomic is not True:
kwargs['atomic'] = self.atomic
+ if self.hints:
+ kwargs['hints'] = self.hints
return (
self.__class__.__name__,
[],
@@ -163,16 +171,18 @@ class RunPython(Operation):
pass
def database_forwards(self, app_label, schema_editor, from_state, to_state):
- # We now execute the Python code in a context that contains a 'models'
- # object, representing the versioned models as an app registry.
- # We could try to override the global cache, but then people will still
- # use direct imports, so we go with a documentation approach instead.
- self.code(from_state.apps, schema_editor)
+ if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints):
+ # We now execute the Python code in a context that contains a 'models'
+ # object, representing the versioned models as an app registry.
+ # We could try to override the global cache, but then people will still
+ # use direct imports, so we go with a documentation approach instead.
+ self.code(from_state.apps, schema_editor)
def database_backwards(self, app_label, schema_editor, from_state, to_state):
if self.reverse_code is None:
raise NotImplementedError("You cannot reverse this operation")
- self.reverse_code(from_state.apps, schema_editor)
+ if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints):
+ self.reverse_code(from_state.apps, schema_editor)
def describe(self):
return "Raw Python operation"
diff --git a/django/db/utils.py b/django/db/utils.py
index a355bbe466..fc2203ff47 100644
--- a/django/db/utils.py
+++ b/django/db/utils.py
@@ -316,7 +316,7 @@ class ConnectionRouter(object):
return allow
return obj1._state.db == obj2._state.db
- def allow_migrate(self, db, model):
+ def allow_migrate(self, db, model, **hints):
for router in self.routers:
try:
try:
@@ -331,7 +331,7 @@ class ConnectionRouter(object):
# If the router doesn't have a method, skip to the next one.
pass
else:
- allow = method(db, model)
+ allow = method(db, model, **hints)
if allow is not None:
return allow
return True