mirror of
https://github.com/django/django.git
synced 2025-10-26 15:16:09 +00:00
Fixed #24109 -- Allowed RunSQL and RunPython operations to be elided.
Thanks to Markus Holtermann and Tim Graham for their review.
This commit is contained in:
@@ -30,6 +30,9 @@ class Operation(object):
|
||||
# DDL transaction support (i.e., does it have no DDL, like RunPython)
|
||||
atomic = False
|
||||
|
||||
# Should this operation be considered safe to elide and optimize across?
|
||||
elidable = False
|
||||
|
||||
serialization_expand_args = []
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
@@ -117,6 +120,10 @@ class Operation(object):
|
||||
replaced with or a boolean that indicates whether or not the specified
|
||||
operation can be optimized across.
|
||||
"""
|
||||
if self.elidable:
|
||||
return [operation]
|
||||
elif operation.elidable:
|
||||
return [self]
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
@@ -27,7 +27,10 @@ class FieldOperation(Operation):
|
||||
return self.is_same_model_operation(operation) and self.name_lower == operation.name_lower
|
||||
|
||||
def reduce(self, operation, in_between, app_label=None):
|
||||
return not operation.references_field(self.model_name, self.name, app_label)
|
||||
return (
|
||||
super(FieldOperation, self).reduce(operation, in_between, app_label=app_label) or
|
||||
not operation.references_field(self.model_name, self.name, app_label)
|
||||
)
|
||||
|
||||
|
||||
class AddField(FieldOperation):
|
||||
@@ -333,4 +336,9 @@ class RenameField(FieldOperation):
|
||||
operation.new_name,
|
||||
),
|
||||
]
|
||||
return not operation.references_field(self.model_name, self.new_name, app_label)
|
||||
# Skip `FieldOperation.reduce` as we want to run `references_field`
|
||||
# against self.new_name.
|
||||
return (
|
||||
super(FieldOperation, self).reduce(operation, in_between, app_label=app_label) or
|
||||
not operation.references_field(self.model_name, self.new_name, app_label)
|
||||
)
|
||||
|
||||
@@ -21,7 +21,10 @@ class ModelOperation(Operation):
|
||||
return self.name.lower()
|
||||
|
||||
def reduce(self, operation, in_between, app_label=None):
|
||||
return not operation.references_model(self.name, app_label)
|
||||
return (
|
||||
super(ModelOperation, self).reduce(operation, in_between, app_label=app_label) or
|
||||
not operation.references_model(self.name, app_label)
|
||||
)
|
||||
|
||||
|
||||
class CreateModel(ModelOperation):
|
||||
@@ -365,7 +368,12 @@ class RenameModel(ModelOperation):
|
||||
operation.new_name,
|
||||
),
|
||||
]
|
||||
return not operation.references_model(self.new_name, app_label)
|
||||
# Skip `ModelOperation.reduce` as we want to run `references_model`
|
||||
# against self.new_name.
|
||||
return (
|
||||
super(ModelOperation, self).reduce(operation, in_between, app_label=app_label) or
|
||||
not operation.references_model(self.new_name, app_label)
|
||||
)
|
||||
|
||||
|
||||
class AlterModelTable(ModelOperation):
|
||||
|
||||
@@ -71,11 +71,12 @@ class RunSQL(Operation):
|
||||
"""
|
||||
noop = ''
|
||||
|
||||
def __init__(self, sql, reverse_sql=None, state_operations=None, hints=None):
|
||||
def __init__(self, sql, reverse_sql=None, state_operations=None, hints=None, elidable=False):
|
||||
self.sql = sql
|
||||
self.reverse_sql = reverse_sql
|
||||
self.state_operations = state_operations or []
|
||||
self.hints = hints or {}
|
||||
self.elidable = elidable
|
||||
|
||||
def deconstruct(self):
|
||||
kwargs = {
|
||||
@@ -138,7 +139,7 @@ class RunPython(Operation):
|
||||
|
||||
reduces_to_sql = False
|
||||
|
||||
def __init__(self, code, reverse_code=None, atomic=True, hints=None):
|
||||
def __init__(self, code, reverse_code=None, atomic=True, hints=None, elidable=False):
|
||||
self.atomic = atomic
|
||||
# Forwards code
|
||||
if not callable(code):
|
||||
@@ -152,6 +153,7 @@ class RunPython(Operation):
|
||||
raise ValueError("RunPython must be supplied with callable arguments")
|
||||
self.reverse_code = reverse_code
|
||||
self.hints = hints or {}
|
||||
self.elidable = elidable
|
||||
|
||||
def deconstruct(self):
|
||||
kwargs = {
|
||||
|
||||
Reference in New Issue
Block a user