diff options
| author | Loic Bistuer <loic.bistuer@gmail.com> | 2015-01-09 00:10:10 +0700 |
|---|---|---|
| committer | Loic Bistuer <loic.bistuer@gmail.com> | 2015-01-10 00:30:48 +0700 |
| commit | 8f4877c89d0f28e289399fbb46357623a49e7eb0 (patch) | |
| tree | 928a44b6cdef3f685f80f350af554e1252e9b136 /django | |
| parent | 665e0aa6ec80a48492033a3b2b4ffdfaae3c78eb (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.py | 16 | ||||
| -rw-r--r-- | django/db/migrations/operations/special.py | 30 | ||||
| -rw-r--r-- | django/db/utils.py | 4 |
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 |
