models.py 7.79 KB
Newer Older
1 2
import uuid

3
from django.contrib.contenttypes.fields import (
4
    GenericForeignKey, GenericRelation,
5
)
6
from django.contrib.contenttypes.models import ContentType
7
from django.db import models
8
from django.utils.encoding import python_2_unicode_compatible
9 10


11
# Basic tests
Jason Myers's avatar
Jason Myers committed
12

13
@python_2_unicode_compatible
14 15
class Author(models.Model):
    name = models.CharField(max_length=50, unique=True)
16
    first_book = models.ForeignKey('Book', models.CASCADE, related_name='first_time_authors')
17 18 19
    favorite_authors = models.ManyToManyField(
        'self', through='FavoriteAuthors', symmetrical=False, related_name='favors_me')

20
    def __str__(self):
21 22 23 24 25 26 27
        return self.name

    class Meta:
        ordering = ['id']


class AuthorWithAge(Author):
28
    author = models.OneToOneField(Author, models.CASCADE, parent_link=True)
29 30 31 32
    age = models.IntegerField()


class FavoriteAuthors(models.Model):
33 34
    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')
35 36

    class Meta:
37
        ordering = ['id']
38 39


40
@python_2_unicode_compatible
41
class AuthorAddress(models.Model):
42
    author = models.ForeignKey(Author, models.CASCADE, to_field='name', related_name='addresses')
43 44 45 46 47
    address = models.TextField()

    class Meta:
        ordering = ['id']

48
    def __str__(self):
49 50 51
        return self.address


52
@python_2_unicode_compatible
53 54 55 56
class Book(models.Model):
    title = models.CharField(max_length=255)
    authors = models.ManyToManyField(Author, related_name='books')

57
    def __str__(self):
58 59 60 61 62
        return self.title

    class Meta:
        ordering = ['id']

Jason Myers's avatar
Jason Myers committed
63

64
class BookWithYear(Book):
65
    book = models.OneToOneField(Book, models.CASCADE, parent_link=True)
66 67 68 69 70
    published_year = models.IntegerField()
    aged_authors = models.ManyToManyField(
        AuthorWithAge, related_name='books_with_year')


71
class Bio(models.Model):
72
    author = models.OneToOneField(Author, models.CASCADE)
73 74 75
    books = models.ManyToManyField(Book, blank=True)


76
@python_2_unicode_compatible
77 78 79 80
class Reader(models.Model):
    name = models.CharField(max_length=50)
    books_read = models.ManyToManyField(Book, related_name='read_by')

81
    def __str__(self):
82 83 84 85 86
        return self.name

    class Meta:
        ordering = ['id']

Jason Myers's avatar
Jason Myers committed
87

88
class BookReview(models.Model):
89
    book = models.ForeignKey(BookWithYear, models.CASCADE)
90
    notes = models.TextField(null=True, blank=True)
91 92


93
# Models for default manager tests
Jason Myers's avatar
Jason Myers committed
94

95 96 97 98 99 100 101 102
class Qualification(models.Model):
    name = models.CharField(max_length=10)

    class Meta:
        ordering = ['id']


class TeacherManager(models.Manager):
103 104
    def get_queryset(self):
        return super(TeacherManager, self).get_queryset().prefetch_related('qualifications')
105 106


107
@python_2_unicode_compatible
108 109 110 111 112 113
class Teacher(models.Model):
    name = models.CharField(max_length=50)
    qualifications = models.ManyToManyField(Qualification)

    objects = TeacherManager()

114
    def __str__(self):
115 116 117 118 119 120 121 122 123 124 125 126 127 128
        return "%s (%s)" % (self.name, ", ".join(q.name for q in self.qualifications.all()))

    class Meta:
        ordering = ['id']


class Department(models.Model):
    name = models.CharField(max_length=50)
    teachers = models.ManyToManyField(Teacher)

    class Meta:
        ordering = ['id']


129
# GenericRelation/GenericForeignKey tests
130

131
@python_2_unicode_compatible
132 133
class TaggedItem(models.Model):
    tag = models.SlugField()
134 135 136 137 138
    content_type = models.ForeignKey(
        ContentType,
        models.CASCADE,
        related_name="taggeditem_set2",
    )
139
    object_id = models.PositiveIntegerField()
140
    content_object = GenericForeignKey('content_type', 'object_id')
141 142 143 144 145 146
    created_by_ct = models.ForeignKey(
        ContentType,
        models.SET_NULL,
        null=True,
        related_name='taggeditem_set3',
    )
147
    created_by_fkey = models.PositiveIntegerField(null=True)
148
    created_by = GenericForeignKey('created_by_ct', 'created_by_fkey',)
149 150 151 152 153 154
    favorite_ct = models.ForeignKey(
        ContentType,
        models.SET_NULL,
        null=True,
        related_name='taggeditem_set4',
    )
155
    favorite_fkey = models.CharField(max_length=64, null=True)
156
    favorite = GenericForeignKey('favorite_ct', 'favorite_fkey')
157

158
    def __str__(self):
159 160
        return self.tag

161 162 163
    class Meta:
        ordering = ['id']

164 165 166

class Bookmark(models.Model):
    url = models.URLField()
167
    tags = GenericRelation(TaggedItem, related_query_name='bookmarks')
168
    favorite_tags = GenericRelation(TaggedItem,
169 170
                                    content_type_field='favorite_ct',
                                    object_id_field='favorite_fkey',
171
                                    related_query_name='favorite_bookmarks')
172

173 174 175
    class Meta:
        ordering = ['id']

176

177 178 179 180
class Comment(models.Model):
    comment = models.TextField()

    # Content-object field
181
    content_type = models.ForeignKey(ContentType, models.CASCADE)
Tim Graham's avatar
Tim Graham committed
182
    object_pk = models.TextField()
183
    content_object = GenericForeignKey(ct_field="content_type", fk_field="object_pk")
184

185 186 187
    class Meta:
        ordering = ['id']

188

189
# Models for lookup ordering tests
190 191

class House(models.Model):
192
    name = models.CharField(max_length=50)
193
    address = models.CharField(max_length=255)
194 195
    owner = models.ForeignKey('Person', models.SET_NULL, null=True)
    main_room = models.OneToOneField('Room', models.SET_NULL, related_name='main_room_of', null=True)
196 197 198 199

    class Meta:
        ordering = ['id']

Jason Myers's avatar
Jason Myers committed
200

201 202
class Room(models.Model):
    name = models.CharField(max_length=50)
203
    house = models.ForeignKey(House, models.CASCADE, related_name='rooms')
204 205 206 207 208 209 210 211 212 213 214 215 216 217

    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]

218 219 220 221
    @property
    def all_houses(self):
        return list(self.houses.all())

222 223 224 225
    class Meta:
        ordering = ['id']


226
# Models for nullable FK tests
227

228
@python_2_unicode_compatible
229 230
class Employee(models.Model):
    name = models.CharField(max_length=50)
231
    boss = models.ForeignKey('self', models.SET_NULL, null=True, related_name='serfs')
232

233
    def __str__(self):
234 235 236 237
        return self.name

    class Meta:
        ordering = ['id']
238 239


240
# Ticket #19607
241 242 243 244 245 246 247 248 249 250 251 252

@python_2_unicode_compatible
class LessonEntry(models.Model):
    name1 = models.CharField(max_length=200)
    name2 = models.CharField(max_length=200)

    def __str__(self):
        return "%s %s" % (self.name1, self.name2)


@python_2_unicode_compatible
class WordEntry(models.Model):
253
    lesson_entry = models.ForeignKey(LessonEntry, models.CASCADE)
254 255 256 257
    name = models.CharField(max_length=200)

    def __str__(self):
        return "%s (%s)" % (self.name, self.id)
258 259


260
# Ticket #21410: Regression when related_name="+"
261 262 263 264

@python_2_unicode_compatible
class Author2(models.Model):
    name = models.CharField(max_length=50, unique=True)
265
    first_book = models.ForeignKey('Book', models.CASCADE, related_name='first_time_authors+')
266 267 268 269 270 271 272
    favorite_books = models.ManyToManyField('Book', related_name='+')

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['id']
273 274 275 276 277 278 279 280 281 282 283 284


# 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)
285
    current_room = models.ForeignKey(Room, models.SET_NULL, related_name='fleas', null=True)
286 287
    pets_visited = models.ManyToManyField(Pet, related_name='fleas_hosted')
    people_visited = models.ManyToManyField(Person, related_name='fleas_hosted')