django/tests/prefetch_related/models.py

316 lines
8.1 KiB
Python

import uuid
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models.query import ModelIterable
from django.utils.functional import cached_property
class Author(models.Model):
name = models.CharField(max_length=50, unique=True)
first_book = models.ForeignKey(
"Book", models.CASCADE, related_name="first_time_authors"
)
favorite_authors = models.ManyToManyField(
"self", through="FavoriteAuthors", symmetrical=False, related_name="favors_me"
)
class Meta:
ordering = ["id"]
def __str__(self):
return self.name
class AuthorWithAge(Author):
author = models.OneToOneField(Author, models.CASCADE, parent_link=True)
age = models.IntegerField()
class FavoriteAuthors(models.Model):
author = models.ForeignKey(
Author, models.CASCADE, to_field="name", related_name="i_like"
)
likes_author = models.ForeignKey(
Author, models.CASCADE, to_field="name", related_name="likes_me"
)
class Meta:
ordering = ["id"]
class AuthorAddress(models.Model):
author = models.ForeignKey(
Author, models.CASCADE, to_field="name", related_name="addresses"
)
address = models.TextField()
class Meta:
ordering = ["id"]
class Book(models.Model):
title = models.CharField(max_length=255)
authors = models.ManyToManyField(Author, related_name="books")
class Meta:
ordering = ["id"]
class BookWithYear(Book):
book = models.OneToOneField(Book, models.CASCADE, parent_link=True)
published_year = models.IntegerField()
aged_authors = models.ManyToManyField(AuthorWithAge, related_name="books_with_year")
class Bio(models.Model):
author = models.OneToOneField(
Author,
models.CASCADE,
primary_key=True,
to_field="name",
)
books = models.ManyToManyField(Book, blank=True)
class Reader(models.Model):
name = models.CharField(max_length=50)
books_read = models.ManyToManyField(Book, related_name="read_by")
class Meta:
ordering = ["id"]
def __str__(self):
return self.name
class BookReview(models.Model):
# Intentionally does not have a related name.
book = models.ForeignKey(BookWithYear, models.CASCADE, null=True)
notes = models.TextField(null=True, blank=True)
# Models for default manager tests
class Qualification(models.Model):
name = models.CharField(max_length=10)
class Meta:
ordering = ["id"]
class ModelIterableSubclass(ModelIterable):
pass
class TeacherQuerySet(models.QuerySet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._iterable_class = ModelIterableSubclass
class TeacherManager(models.Manager):
def get_queryset(self):
return super().get_queryset().prefetch_related("qualifications")
class Teacher(models.Model):
name = models.CharField(max_length=50)
qualifications = models.ManyToManyField(Qualification)
objects = TeacherManager()
objects_custom = TeacherQuerySet.as_manager()
class Meta:
ordering = ["id"]
def __str__(self):
return "%s (%s)" % (
self.name,
", ".join(q.name for q in self.qualifications.all()),
)
class Department(models.Model):
name = models.CharField(max_length=50)
teachers = models.ManyToManyField(Teacher)
class Meta:
ordering = ["id"]
# GenericRelation/GenericForeignKey tests
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(
ContentType,
models.CASCADE,
related_name="taggeditem_set2",
)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
created_by_ct = models.ForeignKey(
ContentType,
models.SET_NULL,
null=True,
related_name="taggeditem_set3",
)
created_by_fkey = models.PositiveIntegerField(null=True)
created_by = GenericForeignKey(
"created_by_ct",
"created_by_fkey",
)
favorite_ct = models.ForeignKey(
ContentType,
models.SET_NULL,
null=True,
related_name="taggeditem_set4",
)
favorite_fkey = models.CharField(max_length=64, null=True)
favorite = GenericForeignKey("favorite_ct", "favorite_fkey")
class Meta:
ordering = ["id"]
class Article(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=20)
class Bookmark(models.Model):
url = models.URLField()
tags = GenericRelation(TaggedItem, related_query_name="bookmarks")
favorite_tags = GenericRelation(
TaggedItem,
content_type_field="favorite_ct",
object_id_field="favorite_fkey",
related_query_name="favorite_bookmarks",
)
class Meta:
ordering = ["id"]
class Comment(models.Model):
comment = models.TextField()
# Content-object field
content_type = models.ForeignKey(ContentType, models.CASCADE, null=True)
object_pk = models.TextField()
content_object = GenericForeignKey(ct_field="content_type", fk_field="object_pk")
content_type_uuid = models.ForeignKey(
ContentType, models.CASCADE, related_name="comments", null=True
)
object_pk_uuid = models.TextField()
content_object_uuid = GenericForeignKey(
ct_field="content_type_uuid", fk_field="object_pk_uuid"
)
class Meta:
ordering = ["id"]
# Models for lookup ordering tests
class House(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=255)
owner = models.ForeignKey("Person", models.SET_NULL, null=True)
main_room = models.OneToOneField(
"Room", models.SET_NULL, related_name="main_room_of", null=True
)
class Meta:
ordering = ["id"]
class Room(models.Model):
name = models.CharField(max_length=50)
house = models.ForeignKey(House, models.CASCADE, related_name="rooms")
class Meta:
ordering = ["id"]
class Person(models.Model):
name = models.CharField(max_length=50)
houses = models.ManyToManyField(House, related_name="occupants")
@property
def primary_house(self):
# Assume business logic forces every person to have at least one house.
return sorted(self.houses.all(), key=lambda house: -house.rooms.count())[0]
@property
def all_houses(self):
return list(self.houses.all())
@cached_property
def cached_all_houses(self):
return self.all_houses
class Meta:
ordering = ["id"]
# Models for nullable FK tests
class Employee(models.Model):
name = models.CharField(max_length=50)
boss = models.ForeignKey("self", models.SET_NULL, null=True, related_name="serfs")
class Meta:
ordering = ["id"]
# Ticket #19607
class LessonEntry(models.Model):
name1 = models.CharField(max_length=200)
name2 = models.CharField(max_length=200)
class WordEntry(models.Model):
lesson_entry = models.ForeignKey(LessonEntry, models.CASCADE)
name = models.CharField(max_length=200)
# Ticket #21410: Regression when related_name="+"
class Author2(models.Model):
name = models.CharField(max_length=50, unique=True)
first_book = models.ForeignKey(
"Book", models.CASCADE, related_name="first_time_authors+"
)
favorite_books = models.ManyToManyField("Book", related_name="+")
class Meta:
ordering = ["id"]
# Models for many-to-many with UUID pk test:
class Pet(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=20)
people = models.ManyToManyField(Person, related_name="pets")
class Flea(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
current_room = models.ForeignKey(
Room, models.SET_NULL, related_name="fleas", null=True
)
pets_visited = models.ManyToManyField(Pet, related_name="fleas_hosted")
people_visited = models.ManyToManyField(Person, related_name="fleas_hosted")