Skip to content

Commit c22521a

Browse files
authored
Merge pull request #51 from meshy/many-to-many-duplication
Avoid many to many duplication when using through models
2 parents f021b85 + e32074b commit c22521a

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ Version numbers should follow https://semver.org/spec/v2.0.0.html
2525

2626
- Moved from `setup.py` to `poetry` for building released packages.
2727

28+
### Fixed
29+
30+
- Many-to-many connections aren't added when using explicit through models.
31+
The foreign-key connections from the through table are enough. #46
32+
2833

2934
## [1.2.0] - 2020-03-01
3035

schema_graph/schema.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ def get_field_relationships(model):
6262
one_to_one.append(relationship)
6363
# Many-to-many
6464
elif field.many_to_many and not field.auto_created:
65-
many_to_many.append(relationship)
65+
through_model = getattr(model, field.name).through
66+
# We only add the M2M connection if the through-model is auto-created.
67+
# This stops us from creating two sets of connections (because the
68+
# connections will be created by the FK fields on the through model).
69+
if through_model._meta.auto_created:
70+
many_to_many.append(relationship)
6671

6772
return foreign_keys, one_to_one, many_to_many
6873

tests/basic/models.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,12 @@ class OutgoingForeignKey(models.Model):
1919

2020
class OutgoingOneToOne(models.Model):
2121
connected = models.OneToOneField(Target, on_delete=models.CASCADE)
22+
23+
24+
class ThroughTable(models.Model):
25+
source = models.ForeignKey("ManyToManyWithThroughTable", on_delete=models.CASCADE)
26+
target = models.ForeignKey(Target, on_delete=models.CASCADE)
27+
28+
29+
class ManyToManyWithThroughTable(models.Model):
30+
connected = models.ManyToManyField(Target, through=ThroughTable)

tests/test_schema.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ def test_models():
3434
"tests.app_c": ("InterAppOneToOne",),
3535
"tests.app_d": ("InterAppManyToMany", "InterAppProxy"),
3636
"tests.basic": (
37+
"ManyToManyWithThroughTable",
3738
"OutgoingForeignKey",
3839
"OutgoingManyToMany",
3940
"OutgoingOneToOne",
4041
"SelfReference",
4142
"Target",
43+
"ThroughTable",
4244
),
4345
"tests.generic": ("GenericFK",),
4446
"tests.inheritance": (
@@ -67,6 +69,11 @@ def test_foreign_key():
6769
(("tests.app_b", "InterAppForeignKey"), ("django.contrib.auth", "User")),
6870
(("tests.basic", "OutgoingForeignKey"), ("tests.basic", "Target")),
6971
(("tests.basic", "SelfReference"), ("tests.basic", "SelfReference")),
72+
(
73+
("tests.basic", "ThroughTable"),
74+
("tests.basic", "ManyToManyWithThroughTable"),
75+
),
76+
(("tests.basic", "ThroughTable"), ("tests.basic", "Target")),
7077
(
7178
("tests.generic", "GenericFK"),
7279
("django.contrib.contenttypes", "ContentType"),

0 commit comments

Comments
 (0)