summaryrefslogtreecommitdiff
path: root/tests/m2m_through
diff options
context:
space:
mode:
authorAkis Kesoglou <akiskesoglou@gmail.com>2014-02-19 20:01:55 +0200
committerAnssi Kääriäinen <akaariai@gmail.com>2014-03-05 22:33:58 +0200
commitc627da0ccc12861163f28177aa7538b420a9d310 (patch)
treed2c3d58f3083bb502f541a9201811e2cdaefd65b /tests/m2m_through
parent95c74b9d699c29fe808684774548e2864d64665a (diff)
Fixed #14549 - Removed restriction of single FKs on intermediary tables
Thanks to Loic Bistuer for review. Minor changes to error messages done by committer.
Diffstat (limited to 'tests/m2m_through')
-rw-r--r--tests/m2m_through/models.py36
-rw-r--r--tests/m2m_through/tests.py29
2 files changed, 64 insertions, 1 deletions
diff --git a/tests/m2m_through/models.py b/tests/m2m_through/models.py
index 70d6baeca8..aaee0aea3b 100644
--- a/tests/m2m_through/models.py
+++ b/tests/m2m_through/models.py
@@ -77,3 +77,39 @@ class Friendship(models.Model):
first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set")
second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set")
date_friended = models.DateTimeField()
+
+
+# Custom through link fields
+@python_2_unicode_compatible
+class Event(models.Model):
+ title = models.CharField(max_length=50)
+ invitees = models.ManyToManyField(Person, through='Invitation', through_fields=('event', 'invitee'), related_name='events_invited')
+
+ def __str__(self):
+ return self.title
+
+
+class Invitation(models.Model):
+ event = models.ForeignKey(Event, related_name='invitations')
+ # field order is deliberately inverted. the target field is "invitee".
+ inviter = models.ForeignKey(Person, related_name='invitations_sent')
+ invitee = models.ForeignKey(Person, related_name='invitations')
+
+
+@python_2_unicode_compatible
+class Employee(models.Model):
+ name = models.CharField(max_length=5)
+ subordinates = models.ManyToManyField('self', through="Relationship", through_fields=('source', 'target'), symmetrical=False)
+
+ class Meta:
+ ordering = ('pk',)
+
+ def __str__(self):
+ return self.name
+
+
+class Relationship(models.Model):
+ # field order is deliberately inverted.
+ another = models.ForeignKey(Employee, related_name="rel_another_set", null=True)
+ target = models.ForeignKey(Employee, related_name="rel_target_set")
+ source = models.ForeignKey(Employee, related_name="rel_source_set")
diff --git a/tests/m2m_through/tests.py b/tests/m2m_through/tests.py
index 0fa3d4aa55..39621bf958 100644
--- a/tests/m2m_through/tests.py
+++ b/tests/m2m_through/tests.py
@@ -6,7 +6,7 @@ from operator import attrgetter
from django.test import TestCase
from .models import (Person, Group, Membership, CustomMembership,
- PersonSelfRefM2M, Friendship)
+ PersonSelfRefM2M, Friendship, Event, Invitation, Employee, Relationship)
class M2mThroughTests(TestCase):
@@ -276,6 +276,33 @@ class M2mThroughTests(TestCase):
attrgetter("name")
)
+ def test_through_fields(self):
+ """
+ Tests that relations with intermediary tables with multiple FKs
+ to the M2M's ``to`` model are possible.
+ """
+ event = Event.objects.create(title='Rockwhale 2014')
+ Invitation.objects.create(event=event, inviter=self.bob, invitee=self.jim)
+ Invitation.objects.create(event=event, inviter=self.bob, invitee=self.jane)
+ self.assertQuerysetEqual(event.invitees.all(), [
+ 'Jane',
+ 'Jim',
+ ], attrgetter('name'))
+
+ def test_through_fields_self_referential(self):
+ john = Employee.objects.create(name='john')
+ peter = Employee.objects.create(name='peter')
+ mary = Employee.objects.create(name='mary')
+ harry = Employee.objects.create(name='harry')
+ Relationship.objects.create(source=john, target=peter, another=None)
+ Relationship.objects.create(source=john, target=mary, another=None)
+ Relationship.objects.create(source=john, target=harry, another=peter)
+ self.assertQuerysetEqual(john.subordinates.all(), [
+ 'peter',
+ 'mary',
+ 'harry',
+ ], attrgetter('name'))
+
def test_query_tests(self):
Membership.objects.create(person=self.jim, group=self.rock)
m2 = Membership.objects.create(person=self.jane, group=self.rock)