1
from django.db import models
3
# No related name is needed here, since symmetrical relations are not
4
# explicitly reversible.
5
class SelfRefer(models.Model):
6
name = models.CharField(max_length=10)
7
references = models.ManyToManyField('self')
8
related = models.ManyToManyField('self')
10
def __unicode__(self):
13
class Tag(models.Model):
14
name = models.CharField(max_length=10)
16
def __unicode__(self):
19
# A related_name is required on one of the ManyToManyField entries here because
20
# they are both addressable as reverse relations from Tag.
21
class Entry(models.Model):
22
name = models.CharField(max_length=10)
23
topics = models.ManyToManyField(Tag)
24
related = models.ManyToManyField(Tag, related_name="similar")
26
def __unicode__(self):
29
# Two models both inheriting from a base model with a self-referential m2m field
30
class SelfReferChild(SelfRefer):
33
class SelfReferChildSibling(SelfRefer):
36
# Many-to-Many relation between models, where one of the PK's isn't an Autofield
37
class Line(models.Model):
38
name = models.CharField(max_length=100)
40
class Worksheet(models.Model):
41
id = models.CharField(primary_key=True, max_length=100)
42
lines = models.ManyToManyField(Line, blank=True, null=True)
44
__test__ = {"regressions": """
45
# Multiple m2m references to the same model or a different model must be
46
# distinguished when accessing the relations through an instance attribute.
48
>>> s1 = SelfRefer.objects.create(name='s1')
49
>>> s2 = SelfRefer.objects.create(name='s2')
50
>>> s3 = SelfRefer.objects.create(name='s3')
51
>>> s1.references.add(s2)
52
>>> s1.related.add(s3)
54
>>> e1 = Entry.objects.create(name='e1')
55
>>> t1 = Tag.objects.create(name='t1')
56
>>> t2 = Tag.objects.create(name='t2')
58
>>> e1.related.add(t2)
60
>>> s1.references.all()
70
# The secret internal related names for self-referential many-to-many fields
71
# shouldn't appear in the list when an error is made.
72
>>> SelfRefer.objects.filter(porcupine='fred')
73
Traceback (most recent call last):
75
FieldError: Cannot resolve keyword 'porcupine' into field. Choices are: id, name, references, related, selfreferchild, selfreferchildsibling
77
# Test to ensure that the relationship between two inherited models
78
# with a self-referential m2m field maintains symmetry
79
>>> sr_child = SelfReferChild(name="Hanna")
82
>>> sr_sibling = SelfReferChildSibling(name="Beth")
84
>>> sr_child.related.add(sr_sibling)
85
>>> sr_child.related.all()
87
>>> sr_sibling.related.all()
90
# Regression for #11311 - The primary key for models in a m2m relation
91
# doesn't have to be an AutoField
92
>>> w = Worksheet(id='abc')