Loading django/db/models/options.py +3 −3 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ from django.conf import settings from django.db.models.fields.related import ManyToManyRel from django.db.models.fields import AutoField, FieldDoesNotExist from django.db.models.fields.proxy import OrderWrt from django.db.models.loading import get_models, app_cache_ready, cache from django.db.models.loading import app_cache_ready, cache from django.utils import six from django.utils.functional import cached_property from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible Loading Loading @@ -495,7 +495,7 @@ class Options(object): cache[obj] = model # Collect also objects which are in relation to some proxy child/parent of self. proxy_cache = cache.copy() for klass in get_models(include_auto_created=True, only_installed=False): for klass in self.app_cache.get_models(include_auto_created=True, only_installed=False): if not klass._meta.swapped: for f in klass._meta.local_fields: if f.rel and not isinstance(f.rel.to, six.string_types) and f.generate_reverse_relation: Loading Loading @@ -538,7 +538,7 @@ class Options(object): cache[obj] = parent else: cache[obj] = model for klass in get_models(only_installed=False): for klass in self.app_cache.get_models(only_installed=False): if not klass._meta.swapped: for f in klass._meta.local_many_to_many: if (f.rel Loading tests/migrations/test_operations.py +8 −1 Original line number Diff line number Diff line Loading @@ -116,7 +116,7 @@ class OperationTests(MigrationTestBase): """ project_state = self.set_up_test_model("test_adflmm", second_model=True) # Test the state alteration operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable")) operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable", related_name="ponies")) new_state = project_state.clone() operation.state_forwards("test_adflmm", new_state) self.assertEqual(len(new_state.models["test_adflmm", "pony"].fields), 4) Loading @@ -126,6 +126,13 @@ class OperationTests(MigrationTestBase): operation.database_forwards("test_adflmm", editor, project_state, new_state) self.assertTableExists("test_adflmm_pony_stables") self.assertColumnNotExists("test_adflmm_pony", "stables") # Make sure the M2M field actually works app_cache = new_state.render() Pony = app_cache.get_model("test_adflmm", "Pony") p = Pony.objects.create(pink=False, weight=4.55) p.stables.create() self.assertEqual(p.stables.count(), 1) p.stables.all().delete() # And test reversal with connection.schema_editor() as editor: operation.database_backwards("test_adflmm", editor, new_state, project_state) Loading tests/schema/models.py +9 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ class BookWithM2M(models.Model): author = models.ForeignKey(Author) title = models.CharField(max_length=100, db_index=True) pub_date = models.DateTimeField() tags = models.ManyToManyField("Tag", related_name="books") tags = models.ManyToManyField("TagM2MTest", related_name="books") class Meta: app_cache = new_app_cache Loading @@ -62,6 +62,14 @@ class Tag(models.Model): app_cache = new_app_cache class TagM2MTest(models.Model): title = models.CharField(max_length=255) slug = models.SlugField(unique=True) class Meta: app_cache = new_app_cache class TagIndexed(models.Model): title = models.CharField(max_length=255) slug = models.SlugField(unique=True) Loading tests/schema/tests.py +12 −12 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ from django.db import connection, DatabaseError, IntegrityError from django.db.models.fields import IntegerField, TextField, CharField, SlugField from django.db.models.fields.related import ManyToManyField, ForeignKey from django.db.transaction import atomic from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagUniqueRename, UniqueTest from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest class SchemaTests(TransactionTestCase): Loading @@ -20,7 +20,7 @@ class SchemaTests(TransactionTestCase): available_apps = [] models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagUniqueRename, UniqueTest] models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest] no_table_strings = ["no such table", "unknown table", "does not exist"] # Utility functions Loading Loading @@ -234,7 +234,7 @@ class SchemaTests(TransactionTestCase): editor.create_model(BookWithM2M) # Ensure there is now an m2m table there columns = self.column_classes(BookWithM2M._meta.get_field_by_name("tags")[0].rel.through) self.assertEqual(columns['tag_id'][0], "IntegerField") self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField") def test_m2m(self): """ Loading @@ -243,9 +243,9 @@ class SchemaTests(TransactionTestCase): # Create the tables with connection.schema_editor() as editor: editor.create_model(AuthorWithM2M) editor.create_model(Tag) editor.create_model(TagM2MTest) # Create an M2M field new_field = ManyToManyField("schema.Tag", related_name="authors") new_field = ManyToManyField("schema.TagM2MTest", related_name="authors") new_field.contribute_to_class(AuthorWithM2M, "tags") try: # Ensure there's no m2m table there Loading @@ -258,7 +258,7 @@ class SchemaTests(TransactionTestCase): ) # Ensure there is now an m2m table there columns = self.column_classes(new_field.rel.through) self.assertEqual(columns['tag_id'][0], "IntegerField") self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField") # Remove the M2M table again with connection.schema_editor() as editor: editor.remove_field( Loading @@ -279,17 +279,17 @@ class SchemaTests(TransactionTestCase): with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(BookWithM2M) editor.create_model(Tag) editor.create_model(TagM2MTest) editor.create_model(UniqueTest) # Ensure the M2M exists and points to Tag # 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'] == ["tag_id"] and details['foreign_key']: self.assertEqual(details['foreign_key'], ('schema_tag', 'id')) 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 tag_id found") self.fail("No FK constraint for tagm2mtest_id found") # Repoint the M2M new_field = ManyToManyField(UniqueTest) new_field.contribute_to_class(BookWithM2M, "uniques") Loading @@ -310,7 +310,7 @@ class SchemaTests(TransactionTestCase): self.assertEqual(details['foreign_key'], ('schema_uniquetest', 'id')) break else: self.fail("No FK constraint for tag_id found") self.fail("No FK constraint for uniquetest_id found") finally: # Cleanup model states BookWithM2M._meta.local_many_to_many.remove(new_field) Loading Loading
django/db/models/options.py +3 −3 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ from django.conf import settings from django.db.models.fields.related import ManyToManyRel from django.db.models.fields import AutoField, FieldDoesNotExist from django.db.models.fields.proxy import OrderWrt from django.db.models.loading import get_models, app_cache_ready, cache from django.db.models.loading import app_cache_ready, cache from django.utils import six from django.utils.functional import cached_property from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible Loading Loading @@ -495,7 +495,7 @@ class Options(object): cache[obj] = model # Collect also objects which are in relation to some proxy child/parent of self. proxy_cache = cache.copy() for klass in get_models(include_auto_created=True, only_installed=False): for klass in self.app_cache.get_models(include_auto_created=True, only_installed=False): if not klass._meta.swapped: for f in klass._meta.local_fields: if f.rel and not isinstance(f.rel.to, six.string_types) and f.generate_reverse_relation: Loading Loading @@ -538,7 +538,7 @@ class Options(object): cache[obj] = parent else: cache[obj] = model for klass in get_models(only_installed=False): for klass in self.app_cache.get_models(only_installed=False): if not klass._meta.swapped: for f in klass._meta.local_many_to_many: if (f.rel Loading
tests/migrations/test_operations.py +8 −1 Original line number Diff line number Diff line Loading @@ -116,7 +116,7 @@ class OperationTests(MigrationTestBase): """ project_state = self.set_up_test_model("test_adflmm", second_model=True) # Test the state alteration operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable")) operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable", related_name="ponies")) new_state = project_state.clone() operation.state_forwards("test_adflmm", new_state) self.assertEqual(len(new_state.models["test_adflmm", "pony"].fields), 4) Loading @@ -126,6 +126,13 @@ class OperationTests(MigrationTestBase): operation.database_forwards("test_adflmm", editor, project_state, new_state) self.assertTableExists("test_adflmm_pony_stables") self.assertColumnNotExists("test_adflmm_pony", "stables") # Make sure the M2M field actually works app_cache = new_state.render() Pony = app_cache.get_model("test_adflmm", "Pony") p = Pony.objects.create(pink=False, weight=4.55) p.stables.create() self.assertEqual(p.stables.count(), 1) p.stables.all().delete() # And test reversal with connection.schema_editor() as editor: operation.database_backwards("test_adflmm", editor, new_state, project_state) Loading
tests/schema/models.py +9 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ class BookWithM2M(models.Model): author = models.ForeignKey(Author) title = models.CharField(max_length=100, db_index=True) pub_date = models.DateTimeField() tags = models.ManyToManyField("Tag", related_name="books") tags = models.ManyToManyField("TagM2MTest", related_name="books") class Meta: app_cache = new_app_cache Loading @@ -62,6 +62,14 @@ class Tag(models.Model): app_cache = new_app_cache class TagM2MTest(models.Model): title = models.CharField(max_length=255) slug = models.SlugField(unique=True) class Meta: app_cache = new_app_cache class TagIndexed(models.Model): title = models.CharField(max_length=255) slug = models.SlugField(unique=True) Loading
tests/schema/tests.py +12 −12 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ from django.db import connection, DatabaseError, IntegrityError from django.db.models.fields import IntegerField, TextField, CharField, SlugField from django.db.models.fields.related import ManyToManyField, ForeignKey from django.db.transaction import atomic from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagUniqueRename, UniqueTest from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest class SchemaTests(TransactionTestCase): Loading @@ -20,7 +20,7 @@ class SchemaTests(TransactionTestCase): available_apps = [] models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagUniqueRename, UniqueTest] models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest] no_table_strings = ["no such table", "unknown table", "does not exist"] # Utility functions Loading Loading @@ -234,7 +234,7 @@ class SchemaTests(TransactionTestCase): editor.create_model(BookWithM2M) # Ensure there is now an m2m table there columns = self.column_classes(BookWithM2M._meta.get_field_by_name("tags")[0].rel.through) self.assertEqual(columns['tag_id'][0], "IntegerField") self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField") def test_m2m(self): """ Loading @@ -243,9 +243,9 @@ class SchemaTests(TransactionTestCase): # Create the tables with connection.schema_editor() as editor: editor.create_model(AuthorWithM2M) editor.create_model(Tag) editor.create_model(TagM2MTest) # Create an M2M field new_field = ManyToManyField("schema.Tag", related_name="authors") new_field = ManyToManyField("schema.TagM2MTest", related_name="authors") new_field.contribute_to_class(AuthorWithM2M, "tags") try: # Ensure there's no m2m table there Loading @@ -258,7 +258,7 @@ class SchemaTests(TransactionTestCase): ) # Ensure there is now an m2m table there columns = self.column_classes(new_field.rel.through) self.assertEqual(columns['tag_id'][0], "IntegerField") self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField") # Remove the M2M table again with connection.schema_editor() as editor: editor.remove_field( Loading @@ -279,17 +279,17 @@ class SchemaTests(TransactionTestCase): with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(BookWithM2M) editor.create_model(Tag) editor.create_model(TagM2MTest) editor.create_model(UniqueTest) # Ensure the M2M exists and points to Tag # 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'] == ["tag_id"] and details['foreign_key']: self.assertEqual(details['foreign_key'], ('schema_tag', 'id')) 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 tag_id found") self.fail("No FK constraint for tagm2mtest_id found") # Repoint the M2M new_field = ManyToManyField(UniqueTest) new_field.contribute_to_class(BookWithM2M, "uniques") Loading @@ -310,7 +310,7 @@ class SchemaTests(TransactionTestCase): self.assertEqual(details['foreign_key'], ('schema_uniquetest', 'id')) break else: self.fail("No FK constraint for tag_id found") self.fail("No FK constraint for uniquetest_id found") finally: # Cleanup model states BookWithM2M._meta.local_many_to_many.remove(new_field) Loading