# Django 1.8.18.dev20170123152445 documentation

# Source code for django.db.migrations.operations.models

    from __future__ import unicode_literals

    from django.db import models
    from django.db.migrations.operations.base import Operation
    from django.db.migrations.state import ModelState
    from django.db.models.options import normalize_together
    from django.utils import six
    from django.utils.functional import cached_property

    class CreateModel(Operation):
        """
        Create a model's table.
        """

        serialization_expand_args = ['fields', 'options', 'managers']

        def __init__(self, name, fields, options=None, bases=None, managers=None):
            self.name = name
            self.fields = fields
            self.options = options or {}
            self.bases = bases or (models.Model,)
            self.managers = managers or []

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
                'fields': self.fields,
            }
            if self.options:
                kwargs['options'] = self.options
            if self.bases and self.bases != (models.Model,):
                kwargs['bases'] = self.bases
            if self.managers and self.managers != [('objects', models.Manager())]:
                kwargs['managers'] = self.managers
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            state.add_model(ModelState(
                app_label,
                self.name,
                list(self.fields),
                dict(self.options),
                tuple(self.bases),
                list(self.managers),
            ))

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            model = to_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, model):
                schema_editor.create_model(model)

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            model = from_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, model):
                schema_editor.delete_model(model)

        def describe(self):
            return "Create %smodel %s" % ("proxy " if self.options.get("proxy", False) else "", self.name)

        def references_model(self, name, app_label=None):
            strings_to_check = [self.name]
            # Check we didn't inherit from the model
            for base in self.bases:
                if isinstance(base, six.string_types):
                    strings_to_check.append(base.split(".")[-1])
            # Check we have no FKs/M2Ms with it
            for fname, field in self.fields:
                if field.rel:
                    if isinstance(field.rel.to, six.string_types):
                        strings_to_check.append(field.rel.to.split(".")[-1])
            # Now go over all the strings and compare them
            for string in strings_to_check:
                if string.lower() == name.lower():
                    return True
            return False

    class DeleteModel(Operation):
        """
        Drops a model's table.
        """

        def __init__(self, name):
            self.name = name

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            state.remove_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            model = from_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, model):
                schema_editor.delete_model(model)

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            model = to_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, model):
                schema_editor.create_model(model)

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Delete model %s" % (self.name, )

    class RenameModel(Operation):
        """
        Renames a model.
        """

        def __init__(self, old_name, new_name):
            self.old_name = old_name
            self.new_name = new_name

        @cached_property
        def old_name_lower(self):
            return self.old_name.lower()

        @cached_property
        def new_name_lower(self):
            return self.new_name.lower()

        def deconstruct(self):
            kwargs = {
                'old_name': self.old_name,
                'new_name': self.new_name,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            apps = state.apps
            model = apps.get_model(app_label, self.old_name)
            model._meta.apps = apps
            # Get all of the related objects we need to repoint
            all_related_objects = (
                f for f in model._meta.get_fields(include_hidden=True)
                if f.auto_created and not f.concrete and (not f.hidden or f.many_to_many)
            )
            # Rename the model
            state.models[app_label, self.new_name_lower] = state.models[app_label, self.old_name_lower]
            state.models[app_label, self.new_name_lower].name = self.new_name
            state.remove_model(app_label, self.old_name_lower)
            # Repoint the FKs and M2Ms pointing to us
            for related_object in all_related_objects:
                if related_object.model is not model:
                    # The model being renamed does not participate in this relation
                    # directly. Rather, a superclass does.
                    continue
                # Use the new related key for self referential related objects.
                if related_object.related_model == model:
                    related_key = (app_label, self.new_name_lower)
                else:
                    related_key = (
                        related_object.related_model._meta.app_label,
                        related_object.related_model._meta.model_name,
                    )
                new_fields = []
                for name, field in state.models[related_key].fields:
                    if name == related_object.field.name:
                        field = field.clone()
                        field.rel.to = "%s.%s" % (app_label, self.new_name)
                    new_fields.append((name, field))
                state.models[related_key].fields = new_fields
                state.reload_model(*related_key)
            state.reload_model(app_label, self.new_name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            new_model = to_state.apps.get_model(app_label, self.new_name)
            if self.allow_migrate_model(schema_editor.connection.alias, new_model):
                old_model = from_state.apps.get_model(app_label, self.old_name)
                # Move the main table
                schema_editor.alter_db_table(
                    new_model,
                    old_model._meta.db_table,
                    new_model._meta.db_table,
                )
                # Alter the fields pointing to us
                for related_object in old_model._meta.related_objects:
                    if related_object.related_model == old_model:
                        model = new_model
                        related_key = (app_label, self.new_name_lower)
                    else:
                        model = related_object.related_model
                        related_key = (
                            related_object.related_model._meta.app_label,
                            related_object.related_model._meta.model_name,
                        )
                    to_field = to_state.apps.get_model(
                        *related_key
                    )._meta.get_field(related_object.field.name)
                    schema_editor.alter_field(
                        model,
                        related_object.field,
                        to_field,
                    )
                # Rename M2M fields whose name is based on this model's name.
                fields = zip(old_model._meta.local_many_to_many, new_model._meta.local_many_to_many)
                for (old_field, new_field) in fields:
                    # Skip self-referential fields as these are renamed above.
                    if new_field.model == new_field.related_model or not new_field.rel.through._meta.auto_created:
                        continue
                    # Rename the M2M table that's based on this model's name.
                    old_m2m_model = old_field.rel.through
                    new_m2m_model = new_field.rel.through
                    schema_editor.alter_db_table(
                        new_m2m_model,
                        old_m2m_model._meta.db_table,
                        new_m2m_model._meta.db_table,
                    )
                    # Rename the column in the M2M table that's based on this
                    # model's name.
                    schema_editor.alter_field(
                        new_m2m_model,
                        old_m2m_model._meta.get_field(old_model._meta.model_name),
                        new_m2m_model._meta.get_field(new_model._meta.model_name),
                    )

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            self.new_name_lower, self.old_name_lower = self.old_name_lower, self.new_name_lower
            self.new_name, self.old_name = self.old_name, self.new_name

            self.database_forwards(app_label, schema_editor, from_state, to_state)

            self.new_name_lower, self.old_name_lower = self.old_name_lower, self.new_name_lower
            self.new_name, self.old_name = self.old_name, self.new_name

        def references_model(self, name, app_label=None):
            return (
                name.lower() == self.old_name_lower or
                name.lower() == self.new_name_lower
            )

        def describe(self):
            return "Rename model %s to %s" % (self.old_name, self.new_name)

    class AlterModelTable(Operation):
        """
        Renames a model's table
        """

        def __init__(self, name, table):
            self.name = name
            self.table = table

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
                'table': self.table,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            state.models[app_label, self.name_lower].options["db_table"] = self.table
            state.reload_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            new_model = to_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, new_model):
                old_model = from_state.apps.get_model(app_label, self.name)
                schema_editor.alter_db_table(
                    new_model,
                    old_model._meta.db_table,
                    new_model._meta.db_table,
                )
                # Rename M2M fields whose name is based on this model's db_table
                for (old_field, new_field) in zip(old_model._meta.local_many_to_many, new_model._meta.local_many_to_many):
                    if new_field.rel.through._meta.auto_created:
                        schema_editor.alter_db_table(
                            new_field.rel.through,
                            old_field.rel.through._meta.db_table,
                            new_field.rel.through._meta.db_table,
                        )

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            return self.database_forwards(app_label, schema_editor, from_state, to_state)

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Rename table for %s to %s" % (self.name, self.table)

    class AlterUniqueTogether(Operation):
        """
        Changes the value of unique_together to the target one.
        Input value of unique_together must be a set of tuples.
        """
        option_name = "unique_together"

        def __init__(self, name, unique_together):
            self.name = name
            unique_together = normalize_together(unique_together)
            self.unique_together = set(tuple(cons) for cons in unique_together)

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
                'unique_together': self.unique_together,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            model_state = state.models[app_label, self.name_lower]
            model_state.options[self.option_name] = self.unique_together
            state.reload_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            new_model = to_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, new_model):
                old_model = from_state.apps.get_model(app_label, self.name)
                schema_editor.alter_unique_together(
                    new_model,
                    getattr(old_model._meta, self.option_name, set()),
                    getattr(new_model._meta, self.option_name, set()),
                )

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            return self.database_forwards(app_label, schema_editor, from_state, to_state)

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.unique_together or ''))

    class AlterIndexTogether(Operation):
        """
        Changes the value of index_together to the target one.
        Input value of index_together must be a set of tuples.
        """
        option_name = "index_together"

        def __init__(self, name, index_together):
            self.name = name
            index_together = normalize_together(index_together)
            self.index_together = set(tuple(cons) for cons in index_together)

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
                'index_together': self.index_together,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            model_state = state.models[app_label, self.name_lower]
            model_state.options[self.option_name] = self.index_together
            state.reload_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            new_model = to_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, new_model):
                old_model = from_state.apps.get_model(app_label, self.name)
                schema_editor.alter_index_together(
                    new_model,
                    getattr(old_model._meta, self.option_name, set()),
                    getattr(new_model._meta, self.option_name, set()),
                )

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            return self.database_forwards(app_label, schema_editor, from_state, to_state)

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.index_together or ''))

    class AlterOrderWithRespectTo(Operation):
        """
        Represents a change with the order_with_respect_to option.
        """

        def __init__(self, name, order_with_respect_to):
            self.name = name
            self.order_with_respect_to = order_with_respect_to

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
                'order_with_respect_to': self.order_with_respect_to,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            model_state = state.models[app_label, self.name_lower]
            model_state.options['order_with_respect_to'] = self.order_with_respect_to
            state.reload_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            to_model = to_state.apps.get_model(app_label, self.name)
            if self.allow_migrate_model(schema_editor.connection.alias, to_model):
                from_model = from_state.apps.get_model(app_label, self.name)
                # Remove a field if we need to
                if from_model._meta.order_with_respect_to and not to_model._meta.order_with_respect_to:
                    schema_editor.remove_field(from_model, from_model._meta.get_field("_order"))
                # Add a field if we need to (altering the column is untouched as
                # it's likely a rename)
                elif to_model._meta.order_with_respect_to and not from_model._meta.order_with_respect_to:
                    field = to_model._meta.get_field("_order")
                    if not field.has_default():
                        field.default = 0
                    schema_editor.add_field(
                        from_model,
                        field,
                    )

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            self.database_forwards(app_label, schema_editor, from_state, to_state)

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Set order_with_respect_to on %s to %s" % (self.name, self.order_with_respect_to)

    class AlterModelOptions(Operation):
        """
        Sets new model options that don't directly affect the database schema
        (like verbose_name, permissions, ordering). Python code in migrations
        may still need them.
        """

        # Model options we want to compare and preserve in an AlterModelOptions op
        ALTER_OPTION_KEYS = [
            "get_latest_by",
            "managed",
            "ordering",
            "permissions",
            "default_permissions",
            "select_on_save",
            "verbose_name",
            "verbose_name_plural",
        ]

        def __init__(self, name, options):
            self.name = name
            self.options = options

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            kwargs = {
                'name': self.name,
                'options': self.options,
            }
            return (
                self.__class__.__name__,
                [],
                kwargs
            )

        def state_forwards(self, app_label, state):
            model_state = state.models[app_label, self.name_lower]
            model_state.options = dict(model_state.options)
            model_state.options.update(self.options)
            for key in self.ALTER_OPTION_KEYS:
                if key not in self.options and key in model_state.options:
                    del model_state.options[key]
            state.reload_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            pass

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            pass

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Change Meta options on %s" % (self.name, )

    class AlterModelManagers(Operation):
        """
        Alters the model's managers
        """

        serialization_expand_args = ['managers']

        def __init__(self, name, managers):
            self.name = name
            self.managers = managers

        @cached_property
        def name_lower(self):
            return self.name.lower()

        def deconstruct(self):
            return (
                self.__class__.__name__,
                [self.name, self.managers],
                {}
            )

        def state_forwards(self, app_label, state):
            model_state = state.models[app_label, self.name_lower]
            model_state.managers = list(self.managers)
            state.reload_model(app_label, self.name_lower)

        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            pass

        def database_backwards(self, app_label, schema_editor, from_state, to_state):
            pass

        def references_model(self, name, app_label=None):
            return name.lower() == self.name_lower

        def describe(self):
            return "Change managers on %s" % (self.name, )