コード例 #1
0
ファイル: recorder.py プロジェクト: 0x008800/Sandbox
 class Meta:
     apps = Apps()
     app_label = "migrations"
     db_table = "django_migrations"
コード例 #2
0
ファイル: test_state.py プロジェクト: zejn/django
 class Meta:
     abstract = True
     apps = Apps()
コード例 #3
0
ファイル: schema.py プロジェクト: rparent/django
    def _remake_table(self,
                      model,
                      create_fields=[],
                      delete_fields=[],
                      alter_fields=[],
                      rename_fields=[],
                      override_uniques=None):
        """
        Shortcut to transform a model from old_model into new_model
        """
        # Work out the new fields dict / mapping
        body = dict((f.name, f) for f in model._meta.local_fields)
        # Since mapping might mix column names and default values,
        # its values must be already quoted.
        mapping = dict((f.column, self.quote_name(f.column))
                       for f in model._meta.local_fields)
        # If any of the new or altered fields is introducing a new PK,
        # remove the old one
        restore_pk_field = None
        if any(f.primary_key
               for f in create_fields) or any(n.primary_key
                                              for o, n in alter_fields):
            for name, field in list(body.items()):
                if field.primary_key:
                    field.primary_key = False
                    restore_pk_field = field
                    if field.auto_created:
                        del body[name]
                        del mapping[field.column]
        # Add in any created fields
        for field in create_fields:
            body[field.name] = field
            # If there's a default, insert it into the copy map
            if field.has_default():
                mapping[field.column] = self.quote_value(
                    self.effective_default(field))
        # Add in any altered fields
        for (old_field, new_field) in alter_fields:
            del body[old_field.name]
            del mapping[old_field.column]
            body[new_field.name] = new_field
            mapping[new_field.column] = self.quote_name(old_field.column)
        # Remove any deleted fields
        for field in delete_fields:
            del body[field.name]
            del mapping[field.column]
            # Remove any implicit M2M tables
            if isinstance(
                    field,
                    ManyToManyField) and field.rel.through._meta.auto_created:
                return self.delete_model(field.rel.through)
        # Work inside a new app registry
        apps = Apps()

        # Provide isolated instances of the fields to the new model body
        # Instantiating the new model with an alternate db_table will alter
        # the internal references of some of the provided fields.
        body = copy.deepcopy(body)

        # Construct a new model for the new state
        meta_contents = {
            'app_label':
            model._meta.app_label,
            'db_table':
            model._meta.db_table + "__new",
            'unique_together':
            model._meta.unique_together
            if override_uniques is None else override_uniques,
            'apps':
            apps,
        }
        meta = type("Meta", tuple(), meta_contents)
        body['Meta'] = meta
        body['__module__'] = model.__module__

        temp_model = type(model._meta.object_name, model.__bases__, body)
        # Create a new table with that format. We remove things from the
        # deferred SQL that match our table name, too
        self.deferred_sql = [
            x for x in self.deferred_sql if model._meta.db_table not in x
        ]
        self.create_model(temp_model)
        # Copy data from the old table
        field_maps = list(mapping.items())
        self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % (
            self.quote_name(temp_model._meta.db_table),
            ', '.join(self.quote_name(x) for x, y in field_maps),
            ', '.join(y for x, y in field_maps),
            self.quote_name(model._meta.db_table),
        ))
        # Delete the old table (not using self.delete_model to avoid deleting
        # all implicit M2M tables)
        self.execute(self.sql_delete_table % {
            "table": self.quote_name(model._meta.db_table),
        })
        # Rename the new to the old
        self.alter_db_table(model, temp_model._meta.db_table,
                            model._meta.db_table)
        # Run deferred SQL on correct table
        for sql in self.deferred_sql:
            self.execute(
                sql.replace(temp_model._meta.db_table, model._meta.db_table))
        self.deferred_sql = []
        # Fix any PK-removed field
        if restore_pk_field:
            restore_pk_field.primary_key = True
コード例 #4
0
    def _remake_table(self,
                      model,
                      create_fields=[],
                      delete_fields=[],
                      alter_fields=[],
                      override_uniques=None,
                      override_indexes=None):
        """
        Shortcut to transform a model from old_model into new_model
        """
        # Work out the new fields dict / mapping
        body = {f.name: f for f in model._meta.local_fields}
        # Since mapping might mix column names and default values,
        # its values must be already quoted.
        mapping = {
            f.column: self.quote_name(f.column)
            for f in model._meta.local_fields
        }
        # This maps field names (not columns) for things like unique_together
        rename_mapping = {}
        # If any of the new or altered fields is introducing a new PK,
        # remove the old one
        restore_pk_field = None
        if any(f.primary_key
               for f in create_fields) or any(n.primary_key
                                              for o, n in alter_fields):
            for name, field in list(body.items()):
                if field.primary_key:
                    field.primary_key = False
                    restore_pk_field = field
                    if field.auto_created:
                        del body[name]
                        del mapping[field.column]
        # Add in any created fields
        for field in create_fields:
            body[field.name] = field
            # Choose a default and insert it into the copy map
            if not field.many_to_many:
                mapping[field.column] = self.quote_value(
                    self.effective_default(field))
        # Add in any altered fields
        for (old_field, new_field) in alter_fields:
            body.pop(old_field.name, None)
            mapping.pop(old_field.column, None)
            body[new_field.name] = new_field
            if old_field.null and not new_field.null:
                case_sql = "coalesce(%(col)s, %(default)s)" % {
                    'col': self.quote_name(old_field.column),
                    'default': self.quote_value(
                        self.effective_default(new_field))
                }
                mapping[new_field.column] = case_sql
            else:
                mapping[new_field.column] = self.quote_name(old_field.column)
            rename_mapping[old_field.name] = new_field.name
        # Remove any deleted fields
        for field in delete_fields:
            del body[field.name]
            del mapping[field.column]
            # Remove any implicit M2M tables
            if field.many_to_many and field.rel.through._meta.auto_created:
                return self.delete_model(field.rel.through)
        # Work inside a new app registry
        apps = Apps()

        # Provide isolated instances of the fields to the new model body
        # Instantiating the new model with an alternate db_table will alter
        # the internal references of some of the provided fields.
        body = copy.deepcopy(body)

        # Work out the new value of unique_together, taking renames into
        # account
        if override_uniques is None:
            override_uniques = [[rename_mapping.get(n, n) for n in unique]
                                for unique in model._meta.unique_together]

        # Work out the new value for index_together, taking renames into
        # account
        if override_indexes is None:
            override_indexes = [[rename_mapping.get(n, n) for n in index]
                                for index in model._meta.index_together]

        # Construct a new model for the new state
        meta_contents = {
            'app_label': model._meta.app_label,
            'db_table': model._meta.db_table + "__new",
            'unique_together': override_uniques,
            'index_together': override_indexes,
            'apps': apps,
        }
        meta = type("Meta", tuple(), meta_contents)
        body['Meta'] = meta
        body['__module__'] = model.__module__

        temp_model = type(model._meta.object_name, model.__bases__, body)
        # Create a new table with that format. We remove things from the
        # deferred SQL that match our table name, too
        self.deferred_sql = [
            x for x in self.deferred_sql if model._meta.db_table not in x
        ]
        self.create_model(temp_model)
        # Copy data from the old table
        field_maps = list(mapping.items())
        self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % (
            self.quote_name(temp_model._meta.db_table),
            ', '.join(self.quote_name(x) for x, y in field_maps),
            ', '.join(y for x, y in field_maps),
            self.quote_name(model._meta.db_table),
        ))
        # Delete the old table
        self.delete_model(model, handle_autom2m=False)
        # Rename the new to the old
        self.alter_db_table(temp_model, temp_model._meta.db_table,
                            model._meta.db_table)
        # Run deferred SQL on correct table
        for sql in self.deferred_sql:
            self.execute(
                sql.replace(temp_model._meta.db_table, model._meta.db_table))
        self.deferred_sql = []
        # Fix any PK-removed field
        if restore_pk_field:
            restore_pk_field.primary_key = True
コード例 #5
0
ファイル: recorder.py プロジェクト: uppercasebrands/django
 class Meta:
     apps = Apps()
     app_label = 'migrations'
     db_table = 'django_migrations'
コード例 #6
0
    def _remake_table(self,
                      model,
                      create_field=None,
                      delete_field=None,
                      alter_field=None):
        """
        Shortcut to transform a model from old_model into new_model

        This follows the correct procedure to perform non-rename or column
        addition operations based on SQLite's documentation

        https://www.sqlite.org/lang_altertable.html#caution

        The essential steps are:
          1. Create a table with the updated definition called "new__app_model"
          2. Copy the data from the existing "app_model" table to the new table
          3. Drop the "app_model" table
          4. Rename the "new__app_model" table to "app_model"
          5. Restore any index of the previous "app_model" table.
        """

        # Self-referential fields must be recreated rather than copied from
        # the old model to ensure their remote_field.field_name doesn't refer
        # to an altered field.
        def is_self_referential(f):
            return f.is_relation and f.remote_field.model is model

        # Work out the new fields dict / mapping
        body = {
            f.name: f.clone() if is_self_referential(f) else f
            for f in model._meta.local_concrete_fields
        }
        # Since mapping might mix column names and default values,
        # its values must be already quoted.
        mapping = {
            f.column: self.quote_name(f.column)
            for f in model._meta.local_concrete_fields
        }
        # This maps field names (not columns) for things like unique_together
        rename_mapping = {}
        # If any of the new or altered fields is introducing a new PK,
        # remove the old one
        restore_pk_field = None
        if getattr(create_field, 'primary_key', False) or (
                alter_field and getattr(alter_field[1], 'primary_key', False)):
            for name, field in list(body.items()):
                if field.primary_key:
                    field.primary_key = False
                    restore_pk_field = field
                    if field.auto_created:
                        del body[name]
                        del mapping[field.column]
        # Add in any created fields
        if create_field:
            body[create_field.name] = create_field
            # Choose a default and insert it into the copy map
            if not create_field.many_to_many and create_field.concrete:
                mapping[create_field.column] = self.quote_value(
                    self.effective_default(create_field))
        # Add in any altered fields
        if alter_field:
            old_field, new_field = alter_field
            body.pop(old_field.name, None)
            mapping.pop(old_field.column, None)
            body[new_field.name] = new_field
            if old_field.null and not new_field.null:
                case_sql = "coalesce(%(col)s, %(default)s)" % {
                    'col': self.quote_name(old_field.column),
                    'default': self.quote_value(
                        self.effective_default(new_field))
                }
                mapping[new_field.column] = case_sql
            else:
                mapping[new_field.column] = self.quote_name(old_field.column)
            rename_mapping[old_field.name] = new_field.name
        # Remove any deleted fields
        if delete_field:
            del body[delete_field.name]
            del mapping[delete_field.column]
            # Remove any implicit M2M tables
            if delete_field.many_to_many and delete_field.remote_field.through._meta.auto_created:
                return self.delete_model(delete_field.remote_field.through)
        # Work inside a new app registry
        apps = Apps()

        # Work out the new value of unique_together, taking renames into
        # account
        unique_together = [[rename_mapping.get(n, n) for n in unique]
                           for unique in model._meta.unique_together]

        # Work out the new value for index_together, taking renames into
        # account
        index_together = [[rename_mapping.get(n, n) for n in index]
                          for index in model._meta.index_together]

        indexes = model._meta.indexes
        if delete_field:
            indexes = [
                index for index in indexes
                if delete_field.name not in index.fields
            ]

        constraints = list(model._meta.constraints)

        # Provide isolated instances of the fields to the new model body so
        # that the existing model's internals aren't interfered with when
        # the dummy model is constructed.
        body_copy = copy.deepcopy(body)

        # Construct a new model with the new fields to allow self referential
        # primary key to resolve to. This model won't ever be materialized as a
        # table and solely exists for foreign key reference resolution purposes.
        # This wouldn't be required if the schema editor was operating on model
        # states instead of rendered models.
        meta_contents = {
            'app_label': model._meta.app_label,
            'db_table': model._meta.db_table,
            'unique_together': unique_together,
            'index_together': index_together,
            'indexes': indexes,
            'constraints': constraints,
            'apps': apps,
        }
        meta = type("Meta", (), meta_contents)
        body_copy['Meta'] = meta
        body_copy['__module__'] = model.__module__
        type(model._meta.object_name, model.__bases__, body_copy)

        # Construct a model with a renamed table name.
        body_copy = copy.deepcopy(body)
        meta_contents = {
            'app_label': model._meta.app_label,
            'db_table': 'new__%s' % strip_quotes(model._meta.db_table),
            'unique_together': unique_together,
            'index_together': index_together,
            'indexes': indexes,
            'constraints': constraints,
            'apps': apps,
        }
        meta = type("Meta", (), meta_contents)
        body_copy['Meta'] = meta
        body_copy['__module__'] = model.__module__
        new_model = type('New%s' % model._meta.object_name, model.__bases__,
                         body_copy)

        # Create a new table with the updated schema.
        self.create_model(new_model)

        # Copy data from the old table into the new table
        self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % (
            self.quote_name(new_model._meta.db_table),
            ', '.join(self.quote_name(x) for x in mapping),
            ', '.join(mapping.values()),
            self.quote_name(model._meta.db_table),
        ))

        # Delete the old table to make way for the new
        self.delete_model(model, handle_autom2m=False)

        # Rename the new table to take way for the old
        self.alter_db_table(
            new_model,
            new_model._meta.db_table,
            model._meta.db_table,
            disable_constraints=False,
        )

        # Run deferred SQL on correct table
        for sql in self.deferred_sql:
            self.execute(sql)
        self.deferred_sql = []
        # Fix any PK-removed field
        if restore_pk_field:
            restore_pk_field.primary_key = True
コード例 #7
0
    def test_add_relations(self):
        """
        #24573 - Adding relations to existing models should reload the
        referenced models too.
        """
        new_apps = Apps()

        class A(models.Model):
            class Meta:
                app_label = 'something'
                apps = new_apps

        class B(A):
            class Meta:
                app_label = 'something'
                apps = new_apps

        class C(models.Model):
            class Meta:
                app_label = 'something'
                apps = new_apps

        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(A))
        project_state.add_model(ModelState.from_model(B))
        project_state.add_model(ModelState.from_model(C))

        project_state.apps  # We need to work with rendered models

        old_state = project_state.clone()
        model_a_old = old_state.apps.get_model('something', 'A')
        model_b_old = old_state.apps.get_model('something', 'B')
        model_c_old = old_state.apps.get_model('something', 'C')
        # Check that the relations between the old models are correct
        self.assertIs(
            model_a_old._meta.get_field('b').related_model, model_b_old)
        self.assertIs(
            model_b_old._meta.get_field('a_ptr').related_model, model_a_old)

        operation = AddField(
            'c', 'to_a',
            models.OneToOneField(
                'something.A',
                models.CASCADE,
                related_name='from_c',
            ))
        operation.state_forwards('something', project_state)
        model_a_new = project_state.apps.get_model('something', 'A')
        model_b_new = project_state.apps.get_model('something', 'B')
        model_c_new = project_state.apps.get_model('something', 'C')

        # Check that all models have changed
        self.assertIsNot(model_a_old, model_a_new)
        self.assertIsNot(model_b_old, model_b_new)
        self.assertIsNot(model_c_old, model_c_new)
        # Check that the relations between the old models still hold
        self.assertIs(
            model_a_old._meta.get_field('b').related_model, model_b_old)
        self.assertIs(
            model_b_old._meta.get_field('a_ptr').related_model, model_a_old)
        # Check that the relations between the new models correct
        self.assertIs(
            model_a_new._meta.get_field('b').related_model, model_b_new)
        self.assertIs(
            model_b_new._meta.get_field('a_ptr').related_model, model_a_new)
        self.assertIs(
            model_a_new._meta.get_field('from_c').related_model, model_c_new)
        self.assertIs(
            model_c_new._meta.get_field('to_a').related_model, model_a_new)
コード例 #8
0
 class Meta:
     apps = Apps()
     app_label = "channels"
     db_table = "django_channel_groups"
     unique_together = [["group", "channel"]]
コード例 #9
0
ファイル: schema.py プロジェクト: zzz-i2p/django-1
    def _remake_table(self,
                      model,
                      create_field=None,
                      delete_field=None,
                      alter_field=None):
        """
        Shortcut to transform a model from old_model into new_model

        The essential steps are:
          1. rename the model's existing table, e.g. "app_model" to "app_model__old"
          2. create a table with the updated definition called "app_model"
          3. copy the data from the old renamed table to the new table
          4. delete the "app_model__old" table
        """

        # Self-referential fields must be recreated rather than copied from
        # the old model to ensure their remote_field.field_name doesn't refer
        # to an altered field.
        def is_self_referential(f):
            return f.is_relation and f.remote_field.model is model

        # Work out the new fields dict / mapping
        body = {
            f.name: f.clone() if is_self_referential(f) else f
            for f in model._meta.local_concrete_fields
        }
        # Since mapping might mix column names and default values,
        # its values must be already quoted.
        mapping = {
            f.column: self.quote_name(f.column)
            for f in model._meta.local_concrete_fields
        }
        # This maps field names (not columns) for things like unique_together
        rename_mapping = {}
        # If any of the new or altered fields is introducing a new PK,
        # remove the old one
        restore_pk_field = None
        if getattr(create_field, 'primary_key', False) or (
                alter_field and getattr(alter_field[1], 'primary_key', False)):
            for name, field in list(body.items()):
                if field.primary_key:
                    field.primary_key = False
                    restore_pk_field = field
                    if field.auto_created:
                        del body[name]
                        del mapping[field.column]
        # Add in any created fields
        if create_field:
            body[create_field.name] = create_field
            # Choose a default and insert it into the copy map
            if not create_field.many_to_many and create_field.concrete:
                mapping[create_field.column] = self.quote_value(
                    self.effective_default(create_field))
        # Add in any altered fields
        if alter_field:
            old_field, new_field = alter_field
            body.pop(old_field.name, None)
            mapping.pop(old_field.column, None)
            body[new_field.name] = new_field
            if old_field.null and not new_field.null:
                case_sql = "coalesce(%(col)s, %(default)s)" % {
                    'col': self.quote_name(old_field.column),
                    'default': self.quote_value(
                        self.effective_default(new_field))
                }
                mapping[new_field.column] = case_sql
            else:
                mapping[new_field.column] = self.quote_name(old_field.column)
            rename_mapping[old_field.name] = new_field.name
        # Remove any deleted fields
        if delete_field:
            del body[delete_field.name]
            del mapping[delete_field.column]
            # Remove any implicit M2M tables
            if delete_field.many_to_many and delete_field.remote_field.through._meta.auto_created:
                return self.delete_model(delete_field.remote_field.through)
        # Work inside a new app registry
        apps = Apps()

        # Provide isolated instances of the fields to the new model body so
        # that the existing model's internals aren't interfered with when
        # the dummy model is constructed.
        body = copy.deepcopy(body)

        # Work out the new value of unique_together, taking renames into
        # account
        unique_together = [[rename_mapping.get(n, n) for n in unique]
                           for unique in model._meta.unique_together]

        # Work out the new value for index_together, taking renames into
        # account
        index_together = [[rename_mapping.get(n, n) for n in index]
                          for index in model._meta.index_together]

        indexes = model._meta.indexes
        if delete_field:
            indexes = [
                index for index in indexes
                if delete_field.name not in index.fields
            ]

        constraints = list(model._meta.constraints)

        # Construct a new model for the new state
        meta_contents = {
            'app_label': model._meta.app_label,
            'db_table': model._meta.db_table,
            'unique_together': unique_together,
            'index_together': index_together,
            'indexes': indexes,
            'constraints': constraints,
            'apps': apps,
        }
        meta = type("Meta", (), meta_contents)
        body['Meta'] = meta
        body['__module__'] = model.__module__

        temp_model = type(model._meta.object_name, model.__bases__, body)

        # We need to modify model._meta.db_table, but everything explodes
        # if the change isn't reversed before the end of this method. This
        # context manager helps us avoid that situation.
        @contextlib.contextmanager
        def altered_table_name(model, temporary_table_name):
            original_table_name = model._meta.db_table
            model._meta.db_table = temporary_table_name
            yield
            model._meta.db_table = original_table_name

        with altered_table_name(model, model._meta.db_table + "__old"):
            # Rename the old table to make way for the new
            self.alter_db_table(
                model,
                temp_model._meta.db_table,
                model._meta.db_table,
                disable_constraints=False,
            )
            # Create a new table with the updated schema.
            self.create_model(temp_model)

            # Copy data from the old table into the new table
            field_maps = list(mapping.items())
            self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % (
                self.quote_name(temp_model._meta.db_table),
                ', '.join(self.quote_name(x) for x, y in field_maps),
                ', '.join(y for x, y in field_maps),
                self.quote_name(model._meta.db_table),
            ))

            # Delete the old table
            self.delete_model(model, handle_autom2m=False)

        # Run deferred SQL on correct table
        for sql in self.deferred_sql:
            self.execute(sql)
        self.deferred_sql = []
        # Fix any PK-removed field
        if restore_pk_field:
            restore_pk_field.primary_key = True
コード例 #10
0
ファイル: test_state.py プロジェクト: rparent/django
    def test_create(self):
        """
        Tests making a ProjectState from an Apps
        """

        new_apps = Apps(["migrations"])

        class Author(models.Model):
            name = models.CharField(max_length=255)
            bio = models.TextField()
            age = models.IntegerField(blank=True, null=True)

            class Meta:
                app_label = "migrations"
                apps = new_apps
                unique_together = ["name", "bio"]
                index_together = ["bio", "age"]

        class AuthorProxy(Author):
            class Meta:
                app_label = "migrations"
                apps = new_apps
                proxy = True
                ordering = ["name"]

        class SubAuthor(Author):
            width = models.FloatField(null=True)

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Book(models.Model):
            title = models.CharField(max_length=1000)
            author = models.ForeignKey(Author)
            contributors = models.ManyToManyField(Author)

            class Meta:
                app_label = "migrations"
                apps = new_apps
                verbose_name = "tome"
                db_table = "test_tome"

        project_state = ProjectState.from_apps(new_apps)
        author_state = project_state.models['migrations', 'author']
        author_proxy_state = project_state.models['migrations', 'authorproxy']
        sub_author_state = project_state.models['migrations', 'subauthor']
        book_state = project_state.models['migrations', 'book']

        self.assertEqual(author_state.app_label, "migrations")
        self.assertEqual(author_state.name, "Author")
        self.assertEqual([x for x, y in author_state.fields], ["id", "name", "bio", "age"])
        self.assertEqual(author_state.fields[1][1].max_length, 255)
        self.assertEqual(author_state.fields[2][1].null, False)
        self.assertEqual(author_state.fields[3][1].null, True)
        self.assertEqual(author_state.options, {"unique_together": set([("name", "bio")]), "index_together": set([("bio", "age")])})
        self.assertEqual(author_state.bases, (models.Model, ))

        self.assertEqual(book_state.app_label, "migrations")
        self.assertEqual(book_state.name, "Book")
        self.assertEqual([x for x, y in book_state.fields], ["id", "title", "author", "contributors"])
        self.assertEqual(book_state.fields[1][1].max_length, 1000)
        self.assertEqual(book_state.fields[2][1].null, False)
        self.assertEqual(book_state.fields[3][1].__class__.__name__, "ManyToManyField")
        self.assertEqual(book_state.options, {"verbose_name": "tome", "db_table": "test_tome"})
        self.assertEqual(book_state.bases, (models.Model, ))

        self.assertEqual(author_proxy_state.app_label, "migrations")
        self.assertEqual(author_proxy_state.name, "AuthorProxy")
        self.assertEqual(author_proxy_state.fields, [])
        self.assertEqual(author_proxy_state.options, {"proxy": True, "ordering": ["name"]})
        self.assertEqual(author_proxy_state.bases, ("migrations.author", ))

        self.assertEqual(sub_author_state.app_label, "migrations")
        self.assertEqual(sub_author_state.name, "SubAuthor")
        self.assertEqual(len(sub_author_state.fields), 2)
        self.assertEqual(sub_author_state.bases, ("migrations.author", ))
コード例 #11
0
 class Meta:
     apps = Apps()
     app_label = "channels"
     db_table = "django_channels"
コード例 #12
0
 class Meta:
     # Disable auto loading of this model as we load it on our own
     apps = Apps()
コード例 #13
0
 class Meta:
     # Disable auto loading of this model as we load it on our own
     apps = Apps()
     verbose_name = 'úñí©óðé µóðéø'
     verbose_name_plural = 'úñí©óðé µóðéøß'
コード例 #14
0
    def _remake_table(self, model, create_field=None, delete_field=None, alter_field=None):
        """
        Shortcut to transform a model from old_model into new_model

        The essential steps are:
          1. rename the model's existing table, e.g. "app_model" to "app_model__old"
          2. create a table with the updated definition called "app_model"
          3. copy the data from the old renamed table to the new table
          4. delete the "app_model__old" table
        """
        # Self-referential fields must be recreated rather than copied from
        # the old model to ensure their remote_field.field_name doesn't refer
        # to an altered field.
        def is_self_referential(f):
            return f.is_relation and f.remote_field.model is model
        # Work out the new fields dict / mapping
        body = {
            f.name: f.clone() if is_self_referential(f) else f
            for f in model._meta.local_concrete_fields
        }
        # Since mapping might mix column names and default values,
        # its values must be already quoted.
        mapping = {f.column: self.quote_name(f.column) for f in model._meta.local_concrete_fields}
        # This maps field names (not columns) for things like unique_together
        rename_mapping = {}
        # If any of the new or altered fields is introducing a new PK,
        # remove the old one
        restore_pk_field = None
        if getattr(create_field, 'primary_key', False) or (
                alter_field and getattr(alter_field[1], 'primary_key', False)):
            for name, field in list(body.items()):
                if field.primary_key:
                    field.primary_key = False
                    restore_pk_field = field
                    if field.auto_created:
                        del body[name]
                        del mapping[field.column]
        # Add in any created fields
        if create_field:
            body[create_field.name] = create_field
            # Choose a default and insert it into the copy map
            if not create_field.many_to_many and create_field.concrete:
                mapping[create_field.column] = self.quote_value(
                    self.effective_default(create_field)
                )
        # Add in any altered fields
        if alter_field:
            old_field, new_field = alter_field
            body.pop(old_field.name, None)
            mapping.pop(old_field.column, None)
            body[new_field.name] = new_field
            if old_field.null and not new_field.null:
                case_sql = "coalesce(%(col)s, %(default)s)" % {
                    'col': self.quote_name(old_field.column),
                    'default': self.quote_value(self.effective_default(new_field))
                }
                mapping[new_field.column] = case_sql
            else:
                mapping[new_field.column] = self.quote_name(old_field.column)
            rename_mapping[old_field.name] = new_field.name
        # Remove any deleted fields
        if delete_field:
            del body[delete_field.name]
            del mapping[delete_field.column]
            # Remove any implicit M2M tables
            if delete_field.many_to_many and delete_field.remote_field.through._meta.auto_created:
                return self.delete_model(delete_field.remote_field.through)
        # Work inside a new app registry
        apps = Apps()

        # Provide isolated instances of the fields to the new model body so
        # that the existing model's internals aren't interfered with when
        # the dummy model is constructed.
        body = copy.deepcopy(body)

        # Work out the new value of unique_together, taking renames into
        # account
        unique_together = [
            [rename_mapping.get(n, n) for n in unique]
            for unique in model._meta.unique_together
        ]

        # Work out the new value for index_together, taking renames into
        # account
        index_together = [
            [rename_mapping.get(n, n) for n in index]
            for index in model._meta.index_together
        ]

        indexes = model._meta.indexes
        if delete_field:
            indexes = [
                index for index in indexes
                if delete_field.name not in index.fields
            ]

        # Construct a new model for the new state
        meta_contents = {
            'app_label': model._meta.app_label,
            'db_table': model._meta.db_table,
            'unique_together': unique_together,
            'index_together': index_together,
            'indexes': indexes,
            'apps': apps,
        }
コード例 #15
0
 def test_wait_for_apps_ready_checks_for_exception(self):
     app_reg = Apps()
     app_reg.ready_event.set()
     # thread.is_alive() is False if it's not started.
     dead_thread = threading.Thread()
     self.assertFalse(self.reloader.wait_for_apps_ready(app_reg, dead_thread))
コード例 #16
0
ファイル: models.py プロジェクト: ikkebr/twitter
from django.apps.registry import Apps
from django.db import models
from django.utils.encoding import python_2_unicode_compatible

# Because we want to test creation and deletion of these as separate things,
# these models are all inserted into a separate Apps so the main test
# runner doesn't migrate them.

new_apps = Apps()


class Author(models.Model):
    name = models.CharField(max_length=255)
    height = models.PositiveIntegerField(null=True, blank=True)

    class Meta:
        apps = new_apps


class AuthorWithM2M(models.Model):
    name = models.CharField(max_length=255)

    class Meta:
        apps = new_apps


class AuthorWithM2MThrough(models.Model):
    name = models.CharField(max_length=255)
    tags = models.ManyToManyField("schema.TagM2MTest",
                                  related_name="authors",
                                  through="AuthorTag")
コード例 #17
0
 def test_wait_for_apps_ready_without_exception(self):
     app_reg = Apps()
     app_reg.ready_event.set()
     thread = mock.MagicMock()
     thread.is_alive.return_value = True
     self.assertTrue(self.reloader.wait_for_apps_ready(app_reg, thread))
コード例 #18
0
 def _remake_table(self,
                   model,
                   create_fields=[],
                   delete_fields=[],
                   alter_fields=[],
                   rename_fields=[],
                   override_uniques=None):
     """
     Shortcut to transform a model from old_model into new_model
     """
     # Work out the new fields dict / mapping
     body = dict((f.name, f) for f in model._meta.local_fields)
     mapping = dict((f.column, f.column) for f in model._meta.local_fields)
     # If any of the new or altered fields is introducing a new PK,
     # remove the old one
     restore_pk_field = None
     if any(f.primary_key
            for f in create_fields) or any(n.primary_key
                                           for o, n in alter_fields):
         for name, field in list(body.items()):
             if field.primary_key:
                 field.primary_key = False
                 restore_pk_field = field
                 if field.auto_created:
                     del body[name]
                     del mapping[field.column]
     # Add in any created fields
     for field in create_fields:
         body[field.name] = field
         # If there's a default, insert it into the copy map
         if field.has_default():
             mapping[field.column] = self.quote_value(field.get_default())
     # Add in any altered fields
     for (old_field, new_field) in alter_fields:
         del body[old_field.name]
         del mapping[old_field.column]
         body[new_field.name] = new_field
         mapping[new_field.column] = old_field.column
     # Remove any deleted fields
     for field in delete_fields:
         del body[field.name]
         del mapping[field.column]
     # Work inside a new app registry
     apps = Apps()
     # Construct a new model for the new state
     meta_contents = {
         'app_label':
         model._meta.app_label,
         'db_table':
         model._meta.db_table + "__new",
         'unique_together':
         model._meta.unique_together
         if override_uniques is None else override_uniques,
         'apps':
         apps,
     }
     meta = type("Meta", tuple(), meta_contents)
     body['Meta'] = meta
     body['__module__'] = model.__module__
     temp_model = type(model._meta.object_name, model.__bases__, body)
     # Create a new table with that format
     self.create_model(temp_model)
     # Copy data from the old table
     field_maps = list(mapping.items())
     self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % (
         self.quote_name(temp_model._meta.db_table),
         ', '.join(self.quote_name(x) for x, y in field_maps),
         ', '.join(self.quote_name(y) for x, y in field_maps),
         self.quote_name(model._meta.db_table),
     ))
     # Delete the old table
     self.delete_model(model)
     # Rename the new to the old
     self.alter_db_table(model, temp_model._meta.db_table,
                         model._meta.db_table)
     # Run deferred SQL on correct table
     for sql in self.deferred_sql:
         self.execute(
             sql.replace(temp_model._meta.db_table, model._meta.db_table))
     self.deferred_sql = []
     # Fix any PK-removed field
     if restore_pk_field:
         restore_pk_field.primary_key = True
コード例 #19
0
 def setUp(self):
     self.apps = Apps(['migrations.related_models_app'])
コード例 #20
0
    def test_dangling_references_throw_error(self):
        new_apps = Apps()

        class Author(models.Model):
            name = models.TextField()

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Publisher(models.Model):
            name = models.TextField()

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Book(models.Model):
            author = models.ForeignKey(Author, models.CASCADE)
            publisher = models.ForeignKey(Publisher, models.CASCADE)

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Magazine(models.Model):
            authors = models.ManyToManyField(Author)

            class Meta:
                app_label = "migrations"
                apps = new_apps

        # Make a valid ProjectState and render it
        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(Author))
        project_state.add_model(ModelState.from_model(Publisher))
        project_state.add_model(ModelState.from_model(Book))
        project_state.add_model(ModelState.from_model(Magazine))
        self.assertEqual(len(project_state.apps.get_models()), 4)

        # now make an invalid one with a ForeignKey
        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(Book))
        msg = (
            "The field migrations.Book.author was declared with a lazy reference "
            "to 'migrations.author', but app 'migrations' doesn't provide model 'author'.\n"
            "The field migrations.Book.publisher was declared with a lazy reference "
            "to 'migrations.publisher', but app 'migrations' doesn't provide model 'publisher'."
        )
        with self.assertRaisesMessage(ValueError, msg):
            project_state.apps

        # And another with ManyToManyField.
        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(Magazine))
        msg = (
            "The field migrations.Magazine.authors was declared with a lazy reference "
            "to 'migrations.author\', but app 'migrations' doesn't provide model 'author'.\n"
            "The field migrations.Magazine_authors.author was declared with a lazy reference "
            "to \'migrations.author\', but app 'migrations' doesn't provide model 'author'."
        )
        with self.assertRaisesMessage(ValueError, msg):
            project_state.apps

        # And now with multiple models and multiple fields.
        project_state.add_model(ModelState.from_model(Book))
        msg = (
            "The field migrations.Book.author was declared with a lazy reference "
            "to 'migrations.author', but app 'migrations' doesn't provide model 'author'.\n"
            "The field migrations.Book.publisher was declared with a lazy reference "
            "to 'migrations.publisher', but app 'migrations' doesn't provide model 'publisher'.\n"
            "The field migrations.Magazine.authors was declared with a lazy reference "
            "to 'migrations.author', but app 'migrations' doesn't provide model 'author'.\n"
            "The field migrations.Magazine_authors.author was declared with a lazy reference "
            "to 'migrations.author', but app 'migrations' doesn't provide model 'author'."
        )
        with self.assertRaisesMessage(ValueError, msg):
            project_state.apps
コード例 #21
0
    def test_dangling_references_throw_error(self):
        new_apps = Apps()

        class Author(models.Model):
            name = models.TextField()

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Publisher(models.Model):
            name = models.TextField()

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Book(models.Model):
            author = models.ForeignKey(Author, models.CASCADE)
            publisher = models.ForeignKey(Publisher, models.CASCADE)

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Magazine(models.Model):
            authors = models.ManyToManyField(Author)

            class Meta:
                app_label = "migrations"
                apps = new_apps

        # Make a valid ProjectState and render it
        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(Author))
        project_state.add_model(ModelState.from_model(Publisher))
        project_state.add_model(ModelState.from_model(Book))
        project_state.add_model(ModelState.from_model(Magazine))
        self.assertEqual(len(project_state.apps.get_models()), 4)

        # now make an invalid one with a ForeignKey
        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(Book))
        msg = (
            "Unhandled pending operations for models:\n"
            "  migrations.author (referred to by fields: migrations.Book.author)\n"
            "  migrations.publisher (referred to by fields: migrations.Book.publisher)"
        )
        with self.assertRaisesMessage(ValueError, msg):
            project_state.apps

        # And another with ManyToManyField.
        project_state = ProjectState()
        project_state.add_model(ModelState.from_model(Magazine))
        msg = (
            "Unhandled pending operations for models:\n"
            "  migrations.author (referred to by fields: "
            "migrations.Magazine.authors, migrations.Magazine_authors.author)")
        with self.assertRaisesMessage(ValueError, msg):
            project_state.apps

        # And now with multiple models and multiple fields.
        project_state.add_model(ModelState.from_model(Book))
        msg = (
            "Unhandled pending operations for models:\n"
            "  migrations.author (referred to by fields: migrations.Book.author, "
            "migrations.Magazine.authors, migrations.Magazine_authors.author)\n"
            "  migrations.publisher (referred to by fields: migrations.Book.publisher)"
        )
        with self.assertRaisesMessage(ValueError, msg):
            project_state.apps
コード例 #22
0
 def render(self,
            include_real=None,
            ignore_swappable=False,
            skip_cache=False):
     "Turns the project state into actual models in a new Apps"
     if self.apps is None or skip_cache:
         # Any apps in self.real_apps should have all their models included
         # in the render. We don't use the original model instances as there
         # are some variables that refer to the Apps object.
         # FKs/M2Ms from real apps are also not included as they just
         # mess things up with partial states (due to lack of dependencies)
         real_models = []
         for app_label in self.real_apps:
             app = global_apps.get_app_config(app_label)
             for model in app.get_models():
                 real_models.append(
                     ModelState.from_model(model, exclude_rels=True))
         # Populate the app registry with a stub for each application.
         app_labels = set(model_state.app_label
                          for model_state in self.models.values())
         self.apps = Apps([
             AppConfigStub(label)
             for label in sorted(self.real_apps + list(app_labels))
         ])
         # We keep trying to render the models in a loop, ignoring invalid
         # base errors, until the size of the unrendered models doesn't
         # decrease by at least one, meaning there's a base dependency loop/
         # missing base.
         unrendered_models = list(self.models.values()) + real_models
         while unrendered_models:
             new_unrendered_models = []
             for model in unrendered_models:
                 try:
                     model.render(self.apps)
                 except InvalidBasesError:
                     new_unrendered_models.append(model)
             if len(new_unrendered_models) == len(unrendered_models):
                 raise InvalidBasesError("Cannot resolve bases for %r" %
                                         new_unrendered_models)
             unrendered_models = new_unrendered_models
         # make sure apps has no dangling references
         if self.apps._pending_lookups:
             # There's some lookups left. See if we can first resolve them
             # ourselves - sometimes fields are added after class_prepared is sent
             for lookup_model, operations in self.apps._pending_lookups.items(
             ):
                 try:
                     model = self.apps.get_model(lookup_model[0],
                                                 lookup_model[1])
                 except LookupError:
                     if "%s.%s" % (
                             lookup_model[0], lookup_model[1]
                     ) == settings.AUTH_USER_MODEL and ignore_swappable:
                         continue
                     # Raise an error with a best-effort helpful message
                     # (only for the first issue). Error message should look like:
                     # "ValueError: Lookup failed for model referenced by
                     # field migrations.Book.author: migrations.Author"
                     raise ValueError(
                         "Lookup failed for model referenced by field {field}: {model[0]}.{model[1]}"
                         .format(
                             field=operations[0][1],
                             model=lookup_model,
                         ))
                 else:
                     do_pending_lookups(model)
     try:
         return self.apps
     finally:
         if skip_cache:
             self.apps = None
コード例 #23
0
ファイル: utils.py プロジェクト: niscee/blog_site
 def enable(self):
     self.old_apps = Options.default_apps
     apps = Apps(self.installed_apps)
     setattr(Options, 'default_apps', apps)
     return apps
コード例 #24
0
 def test_singleton_master(self):
     """
     Ensures that only one master registry can exist.
     """
     with self.assertRaises(RuntimeError):
         Apps(installed_apps=None)
コード例 #25
0
ファイル: test_state.py プロジェクト: zejn/django
    def test_create(self):
        """
        Tests making a ProjectState from an Apps
        """

        new_apps = Apps(["migrations"])

        class Author(models.Model):
            name = models.CharField(max_length=255)
            bio = models.TextField()
            age = models.IntegerField(blank=True, null=True)

            class Meta:
                app_label = "migrations"
                apps = new_apps
                unique_together = ["name", "bio"]
                index_together = ["bio", "age"]

        class AuthorProxy(Author):
            class Meta:
                app_label = "migrations"
                apps = new_apps
                proxy = True
                ordering = ["name"]

        class SubAuthor(Author):
            width = models.FloatField(null=True)

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class Book(models.Model):
            title = models.CharField(max_length=1000)
            author = models.ForeignKey(Author)
            contributors = models.ManyToManyField(Author)

            class Meta:
                app_label = "migrations"
                apps = new_apps
                verbose_name = "tome"
                db_table = "test_tome"

        class Food(models.Model):

            food_mgr = FoodManager('a', 'b')
            food_qs = FoodQuerySet.as_manager()
            food_no_mgr = NoMigrationFoodManager('x', 'y')

            class Meta:
                app_label = "migrations"
                apps = new_apps

        class FoodNoManagers(models.Model):
            class Meta:
                app_label = "migrations"
                apps = new_apps

        class FoodNoDefaultManager(models.Model):

            food_no_mgr = NoMigrationFoodManager('x', 'y')
            food_mgr = FoodManager('a', 'b')
            food_qs = FoodQuerySet.as_manager()

            class Meta:
                app_label = "migrations"
                apps = new_apps

        mgr1 = FoodManager('a', 'b')
        mgr2 = FoodManager('x', 'y', c=3, d=4)

        class FoodOrderedManagers(models.Model):
            # The managers on this model should be ordered by their creation
            # counter and not by the order in model body

            food_no_mgr = NoMigrationFoodManager('x', 'y')
            food_mgr2 = mgr2
            food_mgr1 = mgr1

            class Meta:
                app_label = "migrations"
                apps = new_apps

        project_state = ProjectState.from_apps(new_apps)
        author_state = project_state.models['migrations', 'author']
        author_proxy_state = project_state.models['migrations', 'authorproxy']
        sub_author_state = project_state.models['migrations', 'subauthor']
        book_state = project_state.models['migrations', 'book']
        food_state = project_state.models['migrations', 'food']
        food_no_managers_state = project_state.models['migrations',
                                                      'foodnomanagers']
        food_no_default_manager_state = project_state.models[
            'migrations', 'foodnodefaultmanager']
        food_order_manager_state = project_state.models['migrations',
                                                        'foodorderedmanagers']

        self.assertEqual(author_state.app_label, "migrations")
        self.assertEqual(author_state.name, "Author")
        self.assertEqual([x for x, y in author_state.fields],
                         ["id", "name", "bio", "age"])
        self.assertEqual(author_state.fields[1][1].max_length, 255)
        self.assertEqual(author_state.fields[2][1].null, False)
        self.assertEqual(author_state.fields[3][1].null, True)
        self.assertEqual(
            author_state.options, {
                "unique_together": {("name", "bio")},
                "index_together": {("bio", "age")}
            })
        self.assertEqual(author_state.bases, (models.Model, ))

        self.assertEqual(book_state.app_label, "migrations")
        self.assertEqual(book_state.name, "Book")
        self.assertEqual([x for x, y in book_state.fields],
                         ["id", "title", "author", "contributors"])
        self.assertEqual(book_state.fields[1][1].max_length, 1000)
        self.assertEqual(book_state.fields[2][1].null, False)
        self.assertEqual(book_state.fields[3][1].__class__.__name__,
                         "ManyToManyField")
        self.assertEqual(book_state.options, {
            "verbose_name": "tome",
            "db_table": "test_tome"
        })
        self.assertEqual(book_state.bases, (models.Model, ))

        self.assertEqual(author_proxy_state.app_label, "migrations")
        self.assertEqual(author_proxy_state.name, "AuthorProxy")
        self.assertEqual(author_proxy_state.fields, [])
        self.assertEqual(author_proxy_state.options, {
            "proxy": True,
            "ordering": ["name"]
        })
        self.assertEqual(author_proxy_state.bases, ("migrations.author", ))

        self.assertEqual(sub_author_state.app_label, "migrations")
        self.assertEqual(sub_author_state.name, "SubAuthor")
        self.assertEqual(len(sub_author_state.fields), 2)
        self.assertEqual(sub_author_state.bases, ("migrations.author", ))

        # The default manager is used in migrations
        self.assertEqual([name for name, mgr in food_state.managers],
                         ['food_mgr'])
        self.assertTrue(
            all(
                isinstance(name, six.text_type)
                for name, mgr in food_state.managers))
        self.assertEqual(food_state.managers[0][1].args, ('a', 'b', 1, 2))

        # No explicit managers defined. Migrations will fall back to the default
        self.assertEqual(food_no_managers_state.managers, [])

        # food_mgr is used in migration but isn't the default mgr, hence add the
        # default
        self.assertEqual(
            [name for name, mgr in food_no_default_manager_state.managers],
            ['food_no_mgr', 'food_mgr'])
        self.assertTrue(
            all(
                isinstance(name, six.text_type)
                for name, mgr in food_no_default_manager_state.managers))
        self.assertEqual(
            food_no_default_manager_state.managers[0][1].__class__,
            models.Manager)
        self.assertIsInstance(food_no_default_manager_state.managers[1][1],
                              FoodManager)

        self.assertEqual(
            [name for name, mgr in food_order_manager_state.managers],
            ['food_mgr1', 'food_mgr2'])
        self.assertTrue(
            all(
                isinstance(name, six.text_type)
                for name, mgr in food_order_manager_state.managers))
        self.assertEqual(
            [mgr.args for name, mgr in food_order_manager_state.managers],
            [('a', 'b', 1, 2), ('x', 'y', 3, 4)])
コード例 #26
0
 class Meta:
     verbose_name = 'a model created on the fly'
     app_label = 'my_great_app'
     apps = Apps()
コード例 #27
0
ファイル: test_state.py プロジェクト: zejn/django
 class Meta:
     app_label = "migrations"
     apps = Apps()
コード例 #28
0
from __future__ import unicode_literals

from django.apps.registry import Apps
from django.db import models

# We're testing app registry presence on load, so this is handy.

new_apps = Apps(['apps'])


class TotallyNormal(models.Model):
    name = models.CharField(max_length=255)


class SoAlternative(models.Model):
    name = models.CharField(max_length=255)

    class Meta:
        apps = new_apps