1. from datetime import datetime
    
  2. 
    
  3. from django.db import models
    
  4. 
    
  5. 
    
  6. # M2M described on one of the models
    
  7. class Person(models.Model):
    
  8.     name = models.CharField(max_length=128)
    
  9. 
    
  10.     class Meta:
    
  11.         ordering = ("name",)
    
  12. 
    
  13. 
    
  14. class PersonChild(Person):
    
  15.     pass
    
  16. 
    
  17. 
    
  18. class Group(models.Model):
    
  19.     name = models.CharField(max_length=128)
    
  20.     members = models.ManyToManyField(Person, through="Membership")
    
  21.     custom_members = models.ManyToManyField(
    
  22.         Person, through="CustomMembership", related_name="custom"
    
  23.     )
    
  24.     nodefaultsnonulls = models.ManyToManyField(
    
  25.         Person,
    
  26.         through="TestNoDefaultsOrNulls",
    
  27.         related_name="testnodefaultsnonulls",
    
  28.     )
    
  29. 
    
  30.     class Meta:
    
  31.         ordering = ("name",)
    
  32. 
    
  33. 
    
  34. class Membership(models.Model):
    
  35.     person = models.ForeignKey(Person, models.CASCADE)
    
  36.     group = models.ForeignKey(Group, models.CASCADE)
    
  37.     date_joined = models.DateTimeField(default=datetime.now)
    
  38.     invite_reason = models.CharField(max_length=64, null=True)
    
  39. 
    
  40.     class Meta:
    
  41.         ordering = ("date_joined", "invite_reason", "group")
    
  42. 
    
  43.     def __str__(self):
    
  44.         return "%s is a member of %s" % (self.person.name, self.group.name)
    
  45. 
    
  46. 
    
  47. class CustomMembership(models.Model):
    
  48.     person = models.ForeignKey(
    
  49.         Person,
    
  50.         models.CASCADE,
    
  51.         db_column="custom_person_column",
    
  52.         related_name="custom_person_related_name",
    
  53.     )
    
  54.     group = models.ForeignKey(Group, models.CASCADE)
    
  55.     weird_fk = models.ForeignKey(Membership, models.SET_NULL, null=True)
    
  56.     date_joined = models.DateTimeField(default=datetime.now)
    
  57. 
    
  58.     class Meta:
    
  59.         db_table = "test_table"
    
  60.         ordering = ["date_joined"]
    
  61. 
    
  62.     def __str__(self):
    
  63.         return "%s is a member of %s" % (self.person.name, self.group.name)
    
  64. 
    
  65. 
    
  66. class TestNoDefaultsOrNulls(models.Model):
    
  67.     person = models.ForeignKey(Person, models.CASCADE)
    
  68.     group = models.ForeignKey(Group, models.CASCADE)
    
  69.     nodefaultnonull = models.IntegerField()
    
  70. 
    
  71. 
    
  72. class PersonSelfRefM2M(models.Model):
    
  73.     name = models.CharField(max_length=5)
    
  74.     friends = models.ManyToManyField("self", through="Friendship", symmetrical=False)
    
  75.     sym_friends = models.ManyToManyField(
    
  76.         "self", through="SymmetricalFriendship", symmetrical=True
    
  77.     )
    
  78. 
    
  79. 
    
  80. class Friendship(models.Model):
    
  81.     first = models.ForeignKey(
    
  82.         PersonSelfRefM2M, models.CASCADE, related_name="rel_from_set"
    
  83.     )
    
  84.     second = models.ForeignKey(
    
  85.         PersonSelfRefM2M, models.CASCADE, related_name="rel_to_set"
    
  86.     )
    
  87.     date_friended = models.DateTimeField()
    
  88. 
    
  89. 
    
  90. class SymmetricalFriendship(models.Model):
    
  91.     first = models.ForeignKey(PersonSelfRefM2M, models.CASCADE)
    
  92.     second = models.ForeignKey(PersonSelfRefM2M, models.CASCADE, related_name="+")
    
  93.     date_friended = models.DateField()
    
  94. 
    
  95. 
    
  96. # Custom through link fields
    
  97. class Event(models.Model):
    
  98.     title = models.CharField(max_length=50)
    
  99.     invitees = models.ManyToManyField(
    
  100.         to=Person,
    
  101.         through="Invitation",
    
  102.         through_fields=["event", "invitee"],
    
  103.         related_name="events_invited",
    
  104.     )
    
  105. 
    
  106. 
    
  107. class Invitation(models.Model):
    
  108.     event = models.ForeignKey(Event, models.CASCADE, related_name="invitations")
    
  109.     # field order is deliberately inverted. the target field is "invitee".
    
  110.     inviter = models.ForeignKey(Person, models.CASCADE, related_name="invitations_sent")
    
  111.     invitee = models.ForeignKey(Person, models.CASCADE, related_name="invitations")
    
  112. 
    
  113. 
    
  114. class Employee(models.Model):
    
  115.     name = models.CharField(max_length=5)
    
  116.     subordinates = models.ManyToManyField(
    
  117.         "self",
    
  118.         through="Relationship",
    
  119.         through_fields=("source", "target"),
    
  120.         symmetrical=False,
    
  121.     )
    
  122. 
    
  123.     class Meta:
    
  124.         ordering = ("pk",)
    
  125. 
    
  126. 
    
  127. class Relationship(models.Model):
    
  128.     # field order is deliberately inverted.
    
  129.     another = models.ForeignKey(
    
  130.         Employee, models.SET_NULL, related_name="rel_another_set", null=True
    
  131.     )
    
  132.     target = models.ForeignKey(Employee, models.CASCADE, related_name="rel_target_set")
    
  133.     source = models.ForeignKey(Employee, models.CASCADE, related_name="rel_source_set")
    
  134. 
    
  135. 
    
  136. class Ingredient(models.Model):
    
  137.     iname = models.CharField(max_length=20, unique=True)
    
  138. 
    
  139.     class Meta:
    
  140.         ordering = ("iname",)
    
  141. 
    
  142. 
    
  143. class Recipe(models.Model):
    
  144.     rname = models.CharField(max_length=20, unique=True)
    
  145.     ingredients = models.ManyToManyField(
    
  146.         Ingredient,
    
  147.         through="RecipeIngredient",
    
  148.         related_name="recipes",
    
  149.     )
    
  150. 
    
  151.     class Meta:
    
  152.         ordering = ("rname",)
    
  153. 
    
  154. 
    
  155. class RecipeIngredient(models.Model):
    
  156.     ingredient = models.ForeignKey(Ingredient, models.CASCADE, to_field="iname")
    
  157.     recipe = models.ForeignKey(Recipe, models.CASCADE, to_field="rname")