Skip to content

Commit

Permalink
Fixed #22183: Through M2Ms now correctly handled
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgodwin committed Mar 8, 2014
1 parent cdf6eba commit 6b07804
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 3 deletions.
3 changes: 2 additions & 1 deletion django/db/backends/schema.py
Expand Up @@ -262,7 +262,8 @@ def create_model(self, model):
})
# Make M2M tables
for field in model._meta.local_many_to_many:
self.create_model(field.rel.through)
if field.rel.through._meta.auto_created:
self.create_model(field.rel.through)

def delete_model(self, model):
"""
Expand Down
5 changes: 5 additions & 0 deletions django/db/models/fields/related.py
Expand Up @@ -2032,6 +2032,11 @@ def deconstruct(self):
kwargs['to'] = self.rel.to
else:
kwargs['to'] = "%s.%s" % (self.rel.to._meta.app_label, self.rel.to._meta.object_name)
if getattr(self.rel, 'through', None) is not None:
if isinstance(self.rel.through, six.string_types):
kwargs['through'] = self.rel.through
else:
kwargs['through'] = "%s.%s" % (self.rel.through._meta.app_label, self.rel.through._meta.object_name)
# If swappable is True, then see if we're actually pointing to the target
# of a swap.
swappable_setting = self.swappable_setting
Expand Down
6 changes: 6 additions & 0 deletions tests/field_deconstruction/tests.py
Expand Up @@ -242,6 +242,12 @@ def test_many_to_many_field(self):
self.assertEqual(args, [])
self.assertEqual(kwargs, {"to": "auth.User"})
self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
# Test through
field = models.ManyToManyField("auth.Permission", through="auth.Group")
name, path, args, kwargs = field.deconstruct()
self.assertEqual(path, "django.db.models.ManyToManyField")
self.assertEqual(args, [])
self.assertEqual(kwargs, {"to": "auth.Permission", "through": "auth.Group"})

@override_settings(AUTH_USER_MODEL="auth.Permission")
def test_many_to_many_field_swapped(self):
Expand Down
15 changes: 15 additions & 0 deletions tests/schema/models.py
Expand Up @@ -44,6 +44,21 @@ class Meta:
apps = new_apps


class TagThrough(models.Model):
book = models.ForeignKey("schema.BookWithM2MThrough")
tag = models.ForeignKey("schema.TagM2MTest")

class Meta:
apps = new_apps


class BookWithM2MThrough(models.Model):
tags = models.ManyToManyField("TagM2MTest", related_name="books", through=TagThrough)

class Meta:
apps = new_apps


class BookWithSlug(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100, db_index=True)
Expand Down
18 changes: 16 additions & 2 deletions tests/schema/tests.py
Expand Up @@ -9,7 +9,7 @@
from django.db.transaction import atomic
from .models import (Author, AuthorWithM2M, Book, BookWithLongName,
BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename,
UniqueTest, Thing)
UniqueTest, Thing, TagThrough, BookWithM2MThrough)


class SchemaTests(TransactionTestCase):
Expand All @@ -26,7 +26,7 @@ class SchemaTests(TransactionTestCase):
models = [
Author, AuthorWithM2M, Book, BookWithLongName, BookWithSlug,
BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest,
Thing
Thing, TagThrough, BookWithM2MThrough
]

# Utility functions
Expand Down Expand Up @@ -310,6 +310,20 @@ def test_m2m_create(self):
columns = self.column_classes(BookWithM2M._meta.get_field_by_name("tags")[0].rel.through)
self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField")

def test_m2m_create_through(self):
"""
Tests M2M fields on models during creation with through models
"""
# Create the tables
with connection.schema_editor() as editor:
editor.create_model(TagThrough)
editor.create_model(TagM2MTest)
editor.create_model(BookWithM2MThrough)
# Ensure there is now an m2m table there
columns = self.column_classes(TagThrough)
self.assertEqual(columns['book_id'][0], "IntegerField")
self.assertEqual(columns['tag_id'][0], "IntegerField")

def test_m2m(self):
"""
Tests adding/removing M2M fields on models
Expand Down

0 comments on commit 6b07804

Please sign in to comment.