1
0
mirror of https://github.com/django/django.git synced 2025-10-25 06:36:07 +00:00

Fixed #22583 -- Allowed RunPython and RunSQL to provide hints to the db router.

Thanks Markus Holtermann and Tim Graham for the review.
This commit is contained in:
Loic Bistuer
2015-01-09 00:10:10 +07:00
parent 665e0aa6ec
commit 8f4877c89d
9 changed files with 247 additions and 75 deletions

View File

@@ -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>" % (

View File

@@ -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"