1. import uuid
    
  2. 
    
  3. from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    
  4. from django.contrib.contenttypes.models import ContentType
    
  5. from django.db import models
    
  6. from django.db.models.query import ModelIterable
    
  7. from django.utils.functional import cached_property
    
  8. 
    
  9. 
    
  10. class Author(models.Model):
    
  11.     name = models.CharField(max_length=50, unique=True)
    
  12.     first_book = models.ForeignKey(
    
  13.         "Book", models.CASCADE, related_name="first_time_authors"
    
  14.     )
    
  15.     favorite_authors = models.ManyToManyField(
    
  16.         "self", through="FavoriteAuthors", symmetrical=False, related_name="favors_me"
    
  17.     )
    
  18. 
    
  19.     class Meta:
    
  20.         ordering = ["id"]
    
  21. 
    
  22.     def __str__(self):
    
  23.         return self.name
    
  24. 
    
  25. 
    
  26. class AuthorWithAge(Author):
    
  27.     author = models.OneToOneField(Author, models.CASCADE, parent_link=True)
    
  28.     age = models.IntegerField()
    
  29. 
    
  30. 
    
  31. class FavoriteAuthors(models.Model):
    
  32.     author = models.ForeignKey(
    
  33.         Author, models.CASCADE, to_field="name", related_name="i_like"
    
  34.     )
    
  35.     likes_author = models.ForeignKey(
    
  36.         Author, models.CASCADE, to_field="name", related_name="likes_me"
    
  37.     )
    
  38. 
    
  39.     class Meta:
    
  40.         ordering = ["id"]
    
  41. 
    
  42. 
    
  43. class AuthorAddress(models.Model):
    
  44.     author = models.ForeignKey(
    
  45.         Author, models.CASCADE, to_field="name", related_name="addresses"
    
  46.     )
    
  47.     address = models.TextField()
    
  48. 
    
  49.     class Meta:
    
  50.         ordering = ["id"]
    
  51. 
    
  52. 
    
  53. class Book(models.Model):
    
  54.     title = models.CharField(max_length=255)
    
  55.     authors = models.ManyToManyField(Author, related_name="books")
    
  56. 
    
  57.     class Meta:
    
  58.         ordering = ["id"]
    
  59. 
    
  60. 
    
  61. class BookWithYear(Book):
    
  62.     book = models.OneToOneField(Book, models.CASCADE, parent_link=True)
    
  63.     published_year = models.IntegerField()
    
  64.     aged_authors = models.ManyToManyField(AuthorWithAge, related_name="books_with_year")
    
  65. 
    
  66. 
    
  67. class Bio(models.Model):
    
  68.     author = models.OneToOneField(
    
  69.         Author,
    
  70.         models.CASCADE,
    
  71.         primary_key=True,
    
  72.         to_field="name",
    
  73.     )
    
  74.     books = models.ManyToManyField(Book, blank=True)
    
  75. 
    
  76. 
    
  77. class Reader(models.Model):
    
  78.     name = models.CharField(max_length=50)
    
  79.     books_read = models.ManyToManyField(Book, related_name="read_by")
    
  80. 
    
  81.     class Meta:
    
  82.         ordering = ["id"]
    
  83. 
    
  84.     def __str__(self):
    
  85.         return self.name
    
  86. 
    
  87. 
    
  88. class BookReview(models.Model):
    
  89.     # Intentionally does not have a related name.
    
  90.     book = models.ForeignKey(BookWithYear, models.CASCADE, null=True)
    
  91.     notes = models.TextField(null=True, blank=True)
    
  92. 
    
  93. 
    
  94. # Models for default manager tests
    
  95. 
    
  96. 
    
  97. class Qualification(models.Model):
    
  98.     name = models.CharField(max_length=10)
    
  99. 
    
  100.     class Meta:
    
  101.         ordering = ["id"]
    
  102. 
    
  103. 
    
  104. class ModelIterableSubclass(ModelIterable):
    
  105.     pass
    
  106. 
    
  107. 
    
  108. class TeacherQuerySet(models.QuerySet):
    
  109.     def __init__(self, *args, **kwargs):
    
  110.         super().__init__(*args, **kwargs)
    
  111.         self._iterable_class = ModelIterableSubclass
    
  112. 
    
  113. 
    
  114. class TeacherManager(models.Manager):
    
  115.     def get_queryset(self):
    
  116.         return super().get_queryset().prefetch_related("qualifications")
    
  117. 
    
  118. 
    
  119. class Teacher(models.Model):
    
  120.     name = models.CharField(max_length=50)
    
  121.     qualifications = models.ManyToManyField(Qualification)
    
  122. 
    
  123.     objects = TeacherManager()
    
  124.     objects_custom = TeacherQuerySet.as_manager()
    
  125. 
    
  126.     class Meta:
    
  127.         ordering = ["id"]
    
  128. 
    
  129.     def __str__(self):
    
  130.         return "%s (%s)" % (
    
  131.             self.name,
    
  132.             ", ".join(q.name for q in self.qualifications.all()),
    
  133.         )
    
  134. 
    
  135. 
    
  136. class Department(models.Model):
    
  137.     name = models.CharField(max_length=50)
    
  138.     teachers = models.ManyToManyField(Teacher)
    
  139. 
    
  140.     class Meta:
    
  141.         ordering = ["id"]
    
  142. 
    
  143. 
    
  144. # GenericRelation/GenericForeignKey tests
    
  145. 
    
  146. 
    
  147. class TaggedItem(models.Model):
    
  148.     tag = models.SlugField()
    
  149.     content_type = models.ForeignKey(
    
  150.         ContentType,
    
  151.         models.CASCADE,
    
  152.         related_name="taggeditem_set2",
    
  153.     )
    
  154.     object_id = models.PositiveIntegerField()
    
  155.     content_object = GenericForeignKey("content_type", "object_id")
    
  156.     created_by_ct = models.ForeignKey(
    
  157.         ContentType,
    
  158.         models.SET_NULL,
    
  159.         null=True,
    
  160.         related_name="taggeditem_set3",
    
  161.     )
    
  162.     created_by_fkey = models.PositiveIntegerField(null=True)
    
  163.     created_by = GenericForeignKey(
    
  164.         "created_by_ct",
    
  165.         "created_by_fkey",
    
  166.     )
    
  167.     favorite_ct = models.ForeignKey(
    
  168.         ContentType,
    
  169.         models.SET_NULL,
    
  170.         null=True,
    
  171.         related_name="taggeditem_set4",
    
  172.     )
    
  173.     favorite_fkey = models.CharField(max_length=64, null=True)
    
  174.     favorite = GenericForeignKey("favorite_ct", "favorite_fkey")
    
  175. 
    
  176.     class Meta:
    
  177.         ordering = ["id"]
    
  178. 
    
  179. 
    
  180. class Article(models.Model):
    
  181.     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
  182.     name = models.CharField(max_length=20)
    
  183. 
    
  184. 
    
  185. class Bookmark(models.Model):
    
  186.     url = models.URLField()
    
  187.     tags = GenericRelation(TaggedItem, related_query_name="bookmarks")
    
  188.     favorite_tags = GenericRelation(
    
  189.         TaggedItem,
    
  190.         content_type_field="favorite_ct",
    
  191.         object_id_field="favorite_fkey",
    
  192.         related_query_name="favorite_bookmarks",
    
  193.     )
    
  194. 
    
  195.     class Meta:
    
  196.         ordering = ["id"]
    
  197. 
    
  198. 
    
  199. class Comment(models.Model):
    
  200.     comment = models.TextField()
    
  201. 
    
  202.     # Content-object field
    
  203.     content_type = models.ForeignKey(ContentType, models.CASCADE, null=True)
    
  204.     object_pk = models.TextField()
    
  205.     content_object = GenericForeignKey(ct_field="content_type", fk_field="object_pk")
    
  206.     content_type_uuid = models.ForeignKey(
    
  207.         ContentType, models.CASCADE, related_name="comments", null=True
    
  208.     )
    
  209.     object_pk_uuid = models.TextField()
    
  210.     content_object_uuid = GenericForeignKey(
    
  211.         ct_field="content_type_uuid", fk_field="object_pk_uuid"
    
  212.     )
    
  213. 
    
  214.     class Meta:
    
  215.         ordering = ["id"]
    
  216. 
    
  217. 
    
  218. # Models for lookup ordering tests
    
  219. 
    
  220. 
    
  221. class House(models.Model):
    
  222.     name = models.CharField(max_length=50)
    
  223.     address = models.CharField(max_length=255)
    
  224.     owner = models.ForeignKey("Person", models.SET_NULL, null=True)
    
  225.     main_room = models.OneToOneField(
    
  226.         "Room", models.SET_NULL, related_name="main_room_of", null=True
    
  227.     )
    
  228. 
    
  229.     class Meta:
    
  230.         ordering = ["id"]
    
  231. 
    
  232. 
    
  233. class Room(models.Model):
    
  234.     name = models.CharField(max_length=50)
    
  235.     house = models.ForeignKey(House, models.CASCADE, related_name="rooms")
    
  236. 
    
  237.     class Meta:
    
  238.         ordering = ["id"]
    
  239. 
    
  240. 
    
  241. class Person(models.Model):
    
  242.     name = models.CharField(max_length=50)
    
  243.     houses = models.ManyToManyField(House, related_name="occupants")
    
  244. 
    
  245.     @property
    
  246.     def primary_house(self):
    
  247.         # Assume business logic forces every person to have at least one house.
    
  248.         return sorted(self.houses.all(), key=lambda house: -house.rooms.count())[0]
    
  249. 
    
  250.     @property
    
  251.     def all_houses(self):
    
  252.         return list(self.houses.all())
    
  253. 
    
  254.     @cached_property
    
  255.     def cached_all_houses(self):
    
  256.         return self.all_houses
    
  257. 
    
  258.     class Meta:
    
  259.         ordering = ["id"]
    
  260. 
    
  261. 
    
  262. # Models for nullable FK tests
    
  263. 
    
  264. 
    
  265. class Employee(models.Model):
    
  266.     name = models.CharField(max_length=50)
    
  267.     boss = models.ForeignKey("self", models.SET_NULL, null=True, related_name="serfs")
    
  268. 
    
  269.     class Meta:
    
  270.         ordering = ["id"]
    
  271. 
    
  272. 
    
  273. # Ticket #19607
    
  274. 
    
  275. 
    
  276. class LessonEntry(models.Model):
    
  277.     name1 = models.CharField(max_length=200)
    
  278.     name2 = models.CharField(max_length=200)
    
  279. 
    
  280. 
    
  281. class WordEntry(models.Model):
    
  282.     lesson_entry = models.ForeignKey(LessonEntry, models.CASCADE)
    
  283.     name = models.CharField(max_length=200)
    
  284. 
    
  285. 
    
  286. # Ticket #21410: Regression when related_name="+"
    
  287. 
    
  288. 
    
  289. class Author2(models.Model):
    
  290.     name = models.CharField(max_length=50, unique=True)
    
  291.     first_book = models.ForeignKey(
    
  292.         "Book", models.CASCADE, related_name="first_time_authors+"
    
  293.     )
    
  294.     favorite_books = models.ManyToManyField("Book", related_name="+")
    
  295. 
    
  296.     class Meta:
    
  297.         ordering = ["id"]
    
  298. 
    
  299. 
    
  300. # Models for many-to-many with UUID pk test:
    
  301. 
    
  302. 
    
  303. class Pet(models.Model):
    
  304.     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
  305.     name = models.CharField(max_length=20)
    
  306.     people = models.ManyToManyField(Person, related_name="pets")
    
  307. 
    
  308. 
    
  309. class Flea(models.Model):
    
  310.     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
  311.     current_room = models.ForeignKey(
    
  312.         Room, models.SET_NULL, related_name="fleas", null=True
    
  313.     )
    
  314.     pets_visited = models.ManyToManyField(Pet, related_name="fleas_hosted")
    
  315.     people_visited = models.ManyToManyField(Person, related_name="fleas_hosted")