base class for migration operations it s responsible for both mutating the inmemory model state see dbmigrationsstate py to represent what it performs as well as actually performing it against a live database note that some operations won t modify memory state at all e g data copying operations and some will need their modifications to be optionally specified by the user e g custom python code snippets due to the way this class deals with deconstruction it should be considered immutable if this migration can be run in reverse some operations are impossible to reverse like deleting data can this migration be represented as sql things like runpython cannot should this operation be forced as atomic even on backends with no ddl transaction support i e does it have no ddl like runpython should this operation be considered safe to elide and optimize across we capture the arguments to make returning them trivial return a 3tuple of class import path or just name if it lives under django db migrations positional arguments and keyword arguments take the state from the previous migration and mutate it so that it matches what this migration would perform perform the mutation on the database schema in the normal forwards direction perform the mutation on the database schema in the reverse direction e g if this were createmodel it would in fact drop the model s table output a brief summary of what the action does a filename part suitable for automatically naming a migration containing this operation or none if not applicable return true if there is a chance this operation references the given model name as a string with an app label for accuracy used for optimization if in doubt return true returning a false positive will merely make the optimizer a little less efficient while returning a false negative may result in an unusable optimized migration return true if there is a chance this operation references the given field name with an app label for accuracy used for optimization if in doubt return true return whether or not a model may be migrated this is a thin wrapper around router allowmigratemodel that preemptively rejects any proxy swapped out or unmanaged model return either a list of operations the actual operation should be replaced with or a boolean that indicates whether or not the specified operation can be optimized across base class for migration operations it s responsible for both mutating the in memory model state see db migrations state py to represent what it performs as well as actually performing it against a live database note that some operations won t modify memory state at all e g data copying operations and some will need their modifications to be optionally specified by the user e g custom python code snippets due to the way this class deals with deconstruction it should be considered immutable if this migration can be run in reverse some operations are impossible to reverse like deleting data can this migration be represented as sql things like runpython cannot should this operation be forced as atomic even on backends with no ddl transaction support i e does it have no ddl like runpython should this operation be considered safe to elide and optimize across we capture the arguments to make returning them trivial return a 3 tuple of class import path or just name if it lives under django db migrations positional arguments and keyword arguments take the state from the previous migration and mutate it so that it matches what this migration would perform perform the mutation on the database schema in the normal forwards direction perform the mutation on the database schema in the reverse direction e g if this were createmodel it would in fact drop the model s table output a brief summary of what the action does a filename part suitable for automatically naming a migration containing this operation or none if not applicable return true if there is a chance this operation references the given model name as a string with an app label for accuracy used for optimization if in doubt return true returning a false positive will merely make the optimizer a little less efficient while returning a false negative may result in an unusable optimized migration return true if there is a chance this operation references the given field name with an app label for accuracy used for optimization if in doubt return true return whether or not a model may be migrated this is a thin wrapper around router allow_migrate_model that preemptively rejects any proxy swapped out or unmanaged model return either a list of operations the actual operation should be replaced with or a boolean that indicates whether or not the specified operation can be optimized across
from django.db import router


class Operation:
    

    
    
    reversible = True

    
    reduces_to_sql = True

    
    
    atomic = False

    
    elidable = False

    serialization_expand_args = []

    def __new__(cls, *args, **kwargs):
        
        self = object.__new__(cls)
        self._constructor_args = (args, kwargs)
        return self

    def deconstruct(self):
        
        return (
            self.__class__.__name__,
            self._constructor_args[0],
            self._constructor_args[1],
        )

    def state_forwards(self, app_label, state):
        
        raise NotImplementedError(
            "subclasses of Operation must provide a state_forwards() method"
        )

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        
        raise NotImplementedError(
            "subclasses of Operation must provide a database_forwards() method"
        )

    def database_backwards(self, app_label, schema_editor, from_state, to_state):
        
        raise NotImplementedError(
            "subclasses of Operation must provide a database_backwards() method"
        )

    def describe(self):
        
        return "%s: %s" % (self.__class__.__name__, self._constructor_args)

    @property
    def migration_name_fragment(self):
        
        return None

    def references_model(self, name, app_label):
        
        return True

    def references_field(self, model_name, name, app_label):
        
        return self.references_model(model_name, app_label)

    def allow_migrate_model(self, connection_alias, model):
        
        if not model._meta.can_migrate(connection_alias):
            return False

        return router.allow_migrate_model(connection_alias, model)

    def reduce(self, operation, app_label):
        
        if self.elidable:
            return [operation]
        elif operation.elidable:
            return [self]
        return False

    def __repr__(self):
        return "<%s %s%s>" % (
            self.__class__.__name__,
            ", ".join(map(repr, self._constructor_args[0])),
            ",".join(" %s=%r" % x for x in self._constructor_args[1].items()),
        )