def test_m2m_through_alter(self): """ Tests altering M2Ms with explicit through models (should no-op) """ # Create the tables with connection.schema_editor() as editor: editor.create_model(AuthorTag) editor.create_model(AuthorWithM2MThrough) editor.create_model(TagM2MTest) # Ensure the m2m table is there self.assertEqual(len(self.column_classes(AuthorTag)), 3) # "Alter" the field's blankness. This should not actually do anything. with connection.schema_editor() as editor: old_field = AuthorWithM2MThrough._meta.get_field_by_name("tags")[0] new_field = ManyToManyField("schema.TagM2MTest", related_name="authors", through="AuthorTag") new_field.contribute_to_class(AuthorWithM2MThrough, "tags") editor.alter_field( Author, old_field, new_field, ) # Ensure the m2m table is still there self.assertEqual(len(self.column_classes(AuthorTag)), 3)
def test_m2m(self): """ Tests adding/removing M2M fields on models """ # Create the tables with connection.schema_editor() as editor: editor.create_model(AuthorWithM2M) editor.create_model(TagM2MTest) # Create an M2M field new_field = ManyToManyField("schema.TagM2MTest", related_name="authors") new_field.contribute_to_class(AuthorWithM2M, "tags") try: # Ensure there's no m2m table there self.assertRaises(DatabaseError, self.column_classes, new_field.rel.through) # Add the field with connection.schema_editor() as editor: editor.add_field( Author, new_field, ) # Ensure there is now an m2m table there columns = self.column_classes(new_field.rel.through) self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField") # Remove the M2M table again with connection.schema_editor() as editor: editor.remove_field( Author, new_field, ) # Ensure there's no m2m table there self.assertRaises(DatabaseError, self.column_classes, new_field.rel.through) finally: # Cleanup model states AuthorWithM2M._meta.local_many_to_many.remove(new_field)
def test_m2m_db_constraint(self): # Create the table with connection.schema_editor() as editor: editor.create_model(Tag) editor.create_model(Author) # Check that initial tables are there list(Author.objects.all()) list(Tag.objects.all()) # Make a db_constraint=False FK new_field = ManyToManyField("schema.Tag", related_name="authors", db_constraint=False) new_field.contribute_to_class(Author, "tags") # Add the field with connection.schema_editor() as editor: editor.add_field( Author, new_field, ) # Make sure no FK constraint is present constraints = self.get_constraints( new_field.rel.through._meta.db_table) for name, details in constraints.items(): if details['columns'] == ["tag_id"] and details['foreign_key']: self.fail("FK constraint for tag_id found")
def register(model, field_name = None, m2m = False): """ This registers the model class so it can have followers """ from models import Follow if model in registry: return registry.append(model) related_name = 'follow_%s' % model._meta.module_name if not field_name: field_name = model._meta.module_name # Create foreignkeys by default - less sql queries for lookups if m2m: field = ManyToManyField( model, related_name = related_name, ) else: field = ForeignKey( model, related_name = related_name, blank = True, null = True, ) field.contribute_to_class(Follow, field_name) setattr(model, 'followers', followers_for_object) # We need to keep track of which fields and which kind of fields point where model_map[model] = [related_name, field_name, m2m]
def test_m2m(self): """ Tests adding/removing M2M fields on models """ # Create the tables with connection.schema_editor() as editor: editor.create_model(AuthorWithM2M) editor.create_model(TagM2MTest) # Create an M2M field new_field = ManyToManyField("schema.TagM2MTest", related_name="authors") new_field.contribute_to_class(AuthorWithM2M, "tags") try: # Ensure there's no m2m table there self.assertRaises(DatabaseError, self.column_classes, new_field.rel.through) # Add the field with connection.schema_editor() as editor: editor.add_field( Author, new_field, ) # Ensure there is now an m2m table there columns = self.column_classes(new_field.rel.through) self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField") # Remove the M2M table again with connection.schema_editor() as editor: editor.remove_field( Author, new_field, ) # Ensure there's no m2m table there self.assertRaises(DatabaseError, self.column_classes, new_field.rel.through) finally: # Cleanup model states AuthorWithM2M._meta.local_many_to_many.remove(new_field)
def register(model, field_name=None, m2m=False): """ This registers the model class so it can have followers """ from models import Follow if model in registry: return registry.append(model) related_name = 'follow_%s' % model._meta.module_name if not field_name: field_name = model._meta.module_name # Create foreignkeys by default - less sql queries for lookups if m2m: field = ManyToManyField( model, related_name=related_name, ) else: field = ForeignKey( model, related_name=related_name, blank=True, null=True, ) field.contribute_to_class(Follow, field_name) setattr(model, 'followers', followers_for_object) # We need to keep track of which fields and which kind of fields point where model_map[model] = [related_name, field_name, m2m]
def test_m2m_repoint(self): """ Tests repointing M2M fields """ # Create the tables with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(BookWithM2M) editor.create_model(TagM2MTest) editor.create_model(UniqueTest) # Ensure the M2M exists and points to TagM2MTest constraints = connection.introspection.get_constraints( connection.cursor(), BookWithM2M._meta.get_field_by_name("tags") [0].rel.through._meta.db_table) if connection.features.supports_foreign_keys: for name, details in constraints.items(): if details['columns'] == ["tagm2mtest_id" ] and details['foreign_key']: self.assertEqual(details['foreign_key'], ('schema_tagm2mtest', 'id')) break else: self.fail("No FK constraint for tagm2mtest_id found") # Repoint the M2M new_field = ManyToManyField(UniqueTest) new_field.contribute_to_class(BookWithM2M, "uniques") try: with connection.schema_editor() as editor: editor.alter_field( Author, BookWithM2M._meta.get_field_by_name("tags")[0], new_field, ) # Ensure old M2M is gone self.assertRaises( DatabaseError, self.column_classes, BookWithM2M._meta.get_field_by_name("tags")[0].rel.through) # Ensure the new M2M exists and points to UniqueTest constraints = connection.introspection.get_constraints( connection.cursor(), new_field.rel.through._meta.db_table) if connection.features.supports_foreign_keys: for name, details in constraints.items(): if details['columns'] == ["uniquetest_id" ] and details['foreign_key']: self.assertEqual(details['foreign_key'], ('schema_uniquetest', 'id')) break else: self.fail("No FK constraint for uniquetest_id found") finally: # Cleanup through table separately with connection.schema_editor() as editor: editor.remove_field( BookWithM2M, BookWithM2M._meta.get_field_by_name("uniques")[0]) # Cleanup model states BookWithM2M._meta.local_many_to_many.remove(new_field) del BookWithM2M._meta._m2m_cache
def test_m2m_repoint(self): """ Tests repointing M2M fields """ # Create the tables with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(BookWithM2M) editor.create_model(TagM2MTest) editor.create_model(UniqueTest) # Ensure the M2M exists and points to TagM2MTest constraints = connection.introspection.get_constraints( connection.cursor(), BookWithM2M._meta.get_field_by_name("tags")[0].rel.through._meta.db_table ) if connection.features.supports_foreign_keys: for name, details in constraints.items(): if details["columns"] == ["tagm2mtest_id"] and details["foreign_key"]: self.assertEqual(details["foreign_key"], ("schema_tagm2mtest", "id")) break else: self.fail("No FK constraint for tagm2mtest_id found") # Repoint the M2M new_field = ManyToManyField(UniqueTest) new_field.contribute_to_class(BookWithM2M, "uniques") try: with connection.schema_editor() as editor: editor.alter_field(Author, BookWithM2M._meta.get_field_by_name("tags")[0], new_field) # Ensure old M2M is gone self.assertRaises( DatabaseError, self.column_classes, BookWithM2M._meta.get_field_by_name("tags")[0].rel.through ) # Ensure the new M2M exists and points to UniqueTest constraints = connection.introspection.get_constraints( connection.cursor(), new_field.rel.through._meta.db_table ) if connection.features.supports_foreign_keys: for name, details in constraints.items(): if details["columns"] == ["uniquetest_id"] and details["foreign_key"]: self.assertEqual(details["foreign_key"], ("schema_uniquetest", "id")) break else: self.fail("No FK constraint for uniquetest_id found") finally: # Cleanup through table separately with connection.schema_editor() as editor: editor.remove_field(BookWithM2M, BookWithM2M._meta.get_field_by_name("uniques")[0]) # Cleanup model states BookWithM2M._meta.local_many_to_many.remove(new_field) del BookWithM2M._meta._m2m_cache
def test_m2m_through_alter(self): """ Tests altering M2Ms with explicit through models (should no-op) """ # Create the tables with connection.schema_editor() as editor: editor.create_model(AuthorTag) editor.create_model(AuthorWithM2MThrough) editor.create_model(TagM2MTest) # Ensure the m2m table is there self.assertEqual(len(self.column_classes(AuthorTag)), 3) # "Alter" the field's blankness. This should not actually do anything. with connection.schema_editor() as editor: old_field = AuthorWithM2MThrough._meta.get_field_by_name("tags")[0] new_field = ManyToManyField("schema.TagM2MTest", related_name="authors", through="AuthorTag") new_field.contribute_to_class(AuthorWithM2MThrough, "tags") editor.alter_field(Author, old_field, new_field) # Ensure the m2m table is still there self.assertEqual(len(self.column_classes(AuthorTag)), 3)
def test_m2m_db_constraint(self): # Create the table with connection.schema_editor() as editor: editor.create_model(Tag) editor.create_model(Author) # Check that initial tables are there list(Author.objects.all()) list(Tag.objects.all()) # Make a db_constraint=False FK new_field = ManyToManyField("schema.Tag", related_name="authors", db_constraint=False) new_field.contribute_to_class(Author, "tags") # Add the field with connection.schema_editor() as editor: editor.add_field(Author, new_field) # Make sure no FK constraint is present constraints = self.get_constraints(new_field.rel.through._meta.db_table) for name, details in constraints.items(): if details["columns"] == ["tag_id"] and details["foreign_key"]: self.fail("FK constraint for tag_id found")
def register(model, field_name = None, m2m = False): """ This registers the model class so it can have followers, adds a method to the model ``get_followers``, returning the followers - a query set of ``:class:auth.models.User`` objects """ if model in registry: return registry.append(model) related_name = 'follow_%s' % model._meta.module_name # Create foreignkeys by default - less sql queries for lookups if m2m: field = ManyToManyField( model, related_name = related_name, ) else: field = ForeignKey( model, related_name = related_name, blank = True, null = True, ) if not field_name: field_name = model._meta.module_name from models import Follow field.contribute_to_class(Follow, field_name) model.add_to_class('get_followers', get_followers_for_object) # We need to keep track of which fields and which kind of fields point where model_map[model] = [related_name, field_name, m2m]