summaryrefslogtreecommitdiff
path: root/tests/m2m_recursive
diff options
context:
space:
mode:
authorNadège Michel <michel.nadege@gmail.com>2019-04-19 18:12:04 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-06-21 15:03:17 +0200
commit87b1ad6e7351464c60e751b483d9dfce3a2d3382 (patch)
tree24094846d09b2bc43429eb6c187c45b37a8bb2de /tests/m2m_recursive
parenta9179ab032cda80801e7f67ef20db5ee60989f21 (diff)
Fixed #30421 -- Allowed symmetrical intermediate table for self-referential ManyToManyField.
Diffstat (limited to 'tests/m2m_recursive')
-rw-r--r--tests/m2m_recursive/models.py7
-rw-r--r--tests/m2m_recursive/tests.py58
2 files changed, 65 insertions, 0 deletions
diff --git a/tests/m2m_recursive/models.py b/tests/m2m_recursive/models.py
index fd4f4ad166..a9f47770d6 100644
--- a/tests/m2m_recursive/models.py
+++ b/tests/m2m_recursive/models.py
@@ -22,7 +22,14 @@ from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
friends = models.ManyToManyField('self')
+ colleagues = models.ManyToManyField('self', symmetrical=True, through='Colleague')
idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers')
def __str__(self):
return self.name
+
+
+class Colleague(models.Model):
+ first = models.ForeignKey(Person, models.CASCADE)
+ second = models.ForeignKey(Person, models.CASCADE, related_name='+')
+ first_meet = models.DateField()
diff --git a/tests/m2m_recursive/tests.py b/tests/m2m_recursive/tests.py
index 0d992070a2..d0799f07d2 100644
--- a/tests/m2m_recursive/tests.py
+++ b/tests/m2m_recursive/tests.py
@@ -1,3 +1,5 @@
+import datetime
+
from django.test import TestCase
from .models import Person
@@ -59,3 +61,59 @@ class RecursiveM2MTests(TestCase):
self.a.idols.add(self.a)
self.assertSequenceEqual(self.a.idols.all(), [self.a])
self.assertSequenceEqual(self.a.stalkers.all(), [self.a])
+
+
+class RecursiveSymmetricalM2MThroughTests(TestCase):
+ @classmethod
+ def setUpTestData(cls):
+ cls.a, cls.b, cls.c, cls.d = [
+ Person.objects.create(name=name)
+ for name in ['Anne', 'Bill', 'Chuck', 'David']
+ ]
+ cls.a.colleagues.add(cls.b, cls.c, through_defaults={
+ 'first_meet': datetime.date(2013, 1, 5),
+ })
+ # Add m2m for Anne and Chuck in reverse direction.
+ cls.d.colleagues.add(cls.a, cls.c, through_defaults={
+ 'first_meet': datetime.date(2015, 6, 15),
+ })
+
+ def test_recursive_m2m_all(self):
+ for person, colleagues in (
+ (self.a, [self.b, self.c, self.d]),
+ (self.b, [self.a]),
+ (self.c, [self.a, self.d]),
+ (self.d, [self.a, self.c]),
+ ):
+ with self.subTest(person=person):
+ self.assertSequenceEqual(person.colleagues.all(), colleagues)
+
+ def test_recursive_m2m_reverse_add(self):
+ # Add m2m for Anne in reverse direction.
+ self.b.colleagues.add(self.a, through_defaults={
+ 'first_meet': datetime.date(2013, 1, 5),
+ })
+ self.assertSequenceEqual(self.a.colleagues.all(), [self.b, self.c, self.d])
+ self.assertSequenceEqual(self.b.colleagues.all(), [self.a])
+
+ def test_recursive_m2m_remove(self):
+ self.b.colleagues.remove(self.a)
+ self.assertSequenceEqual(self.a.colleagues.all(), [self.c, self.d])
+ self.assertSequenceEqual(self.b.colleagues.all(), [])
+
+ def test_recursive_m2m_clear(self):
+ # Clear m2m for Anne.
+ self.a.colleagues.clear()
+ self.assertSequenceEqual(self.a.friends.all(), [])
+ # Reverse m2m relationships is removed.
+ self.assertSequenceEqual(self.c.colleagues.all(), [self.d])
+ self.assertSequenceEqual(self.d.colleagues.all(), [self.c])
+
+ def test_recursive_m2m_set(self):
+ # Set new relationships for Chuck.
+ self.c.colleagues.set([self.b, self.d], through_defaults={
+ 'first_meet': datetime.date(2013, 1, 5),
+ })
+ self.assertSequenceEqual(self.c.colleagues.order_by('name'), [self.b, self.d])
+ # Reverse m2m relationships is removed.
+ self.assertSequenceEqual(self.a.colleagues.order_by('name'), [self.b, self.d])