1. import datetime
    
  2. import os
    
  3. import tempfile
    
  4. import uuid
    
  5. 
    
  6. from django.core import validators
    
  7. from django.core.exceptions import ValidationError
    
  8. from django.core.files.storage import FileSystemStorage
    
  9. from django.db import models
    
  10. 
    
  11. temp_storage_dir = tempfile.mkdtemp()
    
  12. temp_storage = FileSystemStorage(temp_storage_dir)
    
  13. 
    
  14. 
    
  15. class Person(models.Model):
    
  16.     name = models.CharField(max_length=100)
    
  17. 
    
  18. 
    
  19. class Category(models.Model):
    
  20.     name = models.CharField(max_length=20)
    
  21.     slug = models.SlugField(max_length=20)
    
  22.     url = models.CharField("The URL", max_length=40)
    
  23. 
    
  24.     class Meta:
    
  25.         ordering = ("pk",)
    
  26. 
    
  27.     def __str__(self):
    
  28.         return self.name
    
  29. 
    
  30.     def __repr__(self):
    
  31.         return self.__str__()
    
  32. 
    
  33. 
    
  34. class WriterManager(models.Manager):
    
  35.     def get_queryset(self):
    
  36.         qs = super().get_queryset()
    
  37.         return qs.filter(archived=False)
    
  38. 
    
  39. 
    
  40. class Writer(models.Model):
    
  41.     name = models.CharField(max_length=50, help_text="Use both first and last names.")
    
  42.     archived = models.BooleanField(default=False, editable=False)
    
  43. 
    
  44.     objects = WriterManager()
    
  45. 
    
  46.     class Meta:
    
  47.         ordering = ("name",)
    
  48. 
    
  49.     def __str__(self):
    
  50.         return self.name
    
  51. 
    
  52. 
    
  53. class Article(models.Model):
    
  54.     ARTICLE_STATUS = (
    
  55.         (1, "Draft"),
    
  56.         (2, "Pending"),
    
  57.         (3, "Live"),
    
  58.     )
    
  59.     headline = models.CharField(max_length=50)
    
  60.     slug = models.SlugField()
    
  61.     pub_date = models.DateField()
    
  62.     created = models.DateField(editable=False)
    
  63.     writer = models.ForeignKey(Writer, models.CASCADE)
    
  64.     article = models.TextField()
    
  65.     categories = models.ManyToManyField(Category, blank=True)
    
  66.     status = models.PositiveIntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
    
  67. 
    
  68.     def save(self, *args, **kwargs):
    
  69.         if not self.id:
    
  70.             self.created = datetime.date.today()
    
  71.         return super().save(*args, **kwargs)
    
  72. 
    
  73.     def __str__(self):
    
  74.         return self.headline
    
  75. 
    
  76. 
    
  77. class ImprovedArticle(models.Model):
    
  78.     article = models.OneToOneField(Article, models.CASCADE)
    
  79. 
    
  80. 
    
  81. class ImprovedArticleWithParentLink(models.Model):
    
  82.     article = models.OneToOneField(Article, models.CASCADE, parent_link=True)
    
  83. 
    
  84. 
    
  85. class BetterWriter(Writer):
    
  86.     score = models.IntegerField()
    
  87. 
    
  88. 
    
  89. class Publication(models.Model):
    
  90.     title = models.CharField(max_length=30)
    
  91.     date_published = models.DateField()
    
  92. 
    
  93.     def __str__(self):
    
  94.         return self.title
    
  95. 
    
  96. 
    
  97. def default_mode():
    
  98.     return "di"
    
  99. 
    
  100. 
    
  101. def default_category():
    
  102.     return 3
    
  103. 
    
  104. 
    
  105. class PublicationDefaults(models.Model):
    
  106.     MODE_CHOICES = (("di", "direct"), ("de", "delayed"))
    
  107.     CATEGORY_CHOICES = ((1, "Games"), (2, "Comics"), (3, "Novel"))
    
  108.     title = models.CharField(max_length=30)
    
  109.     date_published = models.DateField(default=datetime.date.today)
    
  110.     datetime_published = models.DateTimeField(default=datetime.datetime(2000, 1, 1))
    
  111.     mode = models.CharField(max_length=2, choices=MODE_CHOICES, default=default_mode)
    
  112.     category = models.IntegerField(choices=CATEGORY_CHOICES, default=default_category)
    
  113.     active = models.BooleanField(default=True)
    
  114.     file = models.FileField(default="default.txt")
    
  115. 
    
  116. 
    
  117. class Author(models.Model):
    
  118.     publication = models.OneToOneField(
    
  119.         Publication, models.SET_NULL, null=True, blank=True
    
  120.     )
    
  121.     full_name = models.CharField(max_length=255)
    
  122. 
    
  123. 
    
  124. class Author1(models.Model):
    
  125.     publication = models.OneToOneField(Publication, models.CASCADE, null=False)
    
  126.     full_name = models.CharField(max_length=255)
    
  127. 
    
  128. 
    
  129. class WriterProfile(models.Model):
    
  130.     writer = models.OneToOneField(Writer, models.CASCADE, primary_key=True)
    
  131.     age = models.PositiveIntegerField()
    
  132. 
    
  133.     def __str__(self):
    
  134.         return "%s is %s" % (self.writer, self.age)
    
  135. 
    
  136. 
    
  137. class Document(models.Model):
    
  138.     myfile = models.FileField(upload_to="unused", blank=True)
    
  139. 
    
  140. 
    
  141. class TextFile(models.Model):
    
  142.     description = models.CharField(max_length=20)
    
  143.     file = models.FileField(storage=temp_storage, upload_to="tests", max_length=15)
    
  144. 
    
  145.     def __str__(self):
    
  146.         return self.description
    
  147. 
    
  148. 
    
  149. class CustomFileField(models.FileField):
    
  150.     def save_form_data(self, instance, data):
    
  151.         been_here = getattr(self, "been_saved", False)
    
  152.         assert not been_here, "save_form_data called more than once"
    
  153.         setattr(self, "been_saved", True)
    
  154. 
    
  155. 
    
  156. class CustomFF(models.Model):
    
  157.     f = CustomFileField(upload_to="unused", blank=True)
    
  158. 
    
  159. 
    
  160. class FilePathModel(models.Model):
    
  161.     path = models.FilePathField(
    
  162.         path=os.path.dirname(__file__), match="models.py", blank=True
    
  163.     )
    
  164. 
    
  165. 
    
  166. try:
    
  167.     from PIL import Image  # NOQA: detect if Pillow is installed
    
  168. 
    
  169.     test_images = True
    
  170. 
    
  171.     class ImageFile(models.Model):
    
  172.         def custom_upload_path(self, filename):
    
  173.             path = self.path or "tests"
    
  174.             return "%s/%s" % (path, filename)
    
  175. 
    
  176.         description = models.CharField(max_length=20)
    
  177. 
    
  178.         # Deliberately put the image field *after* the width/height fields to
    
  179.         # trigger the bug in #10404 with width/height not getting assigned.
    
  180.         width = models.IntegerField(editable=False)
    
  181.         height = models.IntegerField(editable=False)
    
  182.         image = models.ImageField(
    
  183.             storage=temp_storage,
    
  184.             upload_to=custom_upload_path,
    
  185.             width_field="width",
    
  186.             height_field="height",
    
  187.         )
    
  188.         path = models.CharField(max_length=16, blank=True, default="")
    
  189. 
    
  190.         def __str__(self):
    
  191.             return self.description
    
  192. 
    
  193.     class OptionalImageFile(models.Model):
    
  194.         def custom_upload_path(self, filename):
    
  195.             path = self.path or "tests"
    
  196.             return "%s/%s" % (path, filename)
    
  197. 
    
  198.         description = models.CharField(max_length=20)
    
  199.         image = models.ImageField(
    
  200.             storage=temp_storage,
    
  201.             upload_to=custom_upload_path,
    
  202.             width_field="width",
    
  203.             height_field="height",
    
  204.             blank=True,
    
  205.             null=True,
    
  206.         )
    
  207.         width = models.IntegerField(editable=False, null=True)
    
  208.         height = models.IntegerField(editable=False, null=True)
    
  209.         path = models.CharField(max_length=16, blank=True, default="")
    
  210. 
    
  211.         def __str__(self):
    
  212.             return self.description
    
  213. 
    
  214.     class NoExtensionImageFile(models.Model):
    
  215.         def upload_to(self, filename):
    
  216.             return "tests/no_extension"
    
  217. 
    
  218.         description = models.CharField(max_length=20)
    
  219.         image = models.ImageField(storage=temp_storage, upload_to=upload_to)
    
  220. 
    
  221.         def __str__(self):
    
  222.             return self.description
    
  223. 
    
  224. except ImportError:
    
  225.     test_images = False
    
  226. 
    
  227. 
    
  228. class Homepage(models.Model):
    
  229.     url = models.URLField()
    
  230. 
    
  231. 
    
  232. class Product(models.Model):
    
  233.     slug = models.SlugField(unique=True)
    
  234. 
    
  235.     def __str__(self):
    
  236.         return self.slug
    
  237. 
    
  238. 
    
  239. class Price(models.Model):
    
  240.     price = models.DecimalField(max_digits=10, decimal_places=2)
    
  241.     quantity = models.PositiveIntegerField()
    
  242. 
    
  243.     class Meta:
    
  244.         unique_together = (("price", "quantity"),)
    
  245. 
    
  246.     def __str__(self):
    
  247.         return "%s for %s" % (self.quantity, self.price)
    
  248. 
    
  249. 
    
  250. class Triple(models.Model):
    
  251.     left = models.IntegerField()
    
  252.     middle = models.IntegerField()
    
  253.     right = models.IntegerField()
    
  254. 
    
  255.     class Meta:
    
  256.         unique_together = (("left", "middle"), ("middle", "right"))
    
  257. 
    
  258. 
    
  259. class ArticleStatus(models.Model):
    
  260.     ARTICLE_STATUS_CHAR = (
    
  261.         ("d", "Draft"),
    
  262.         ("p", "Pending"),
    
  263.         ("l", "Live"),
    
  264.     )
    
  265.     status = models.CharField(
    
  266.         max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True
    
  267.     )
    
  268. 
    
  269. 
    
  270. class Inventory(models.Model):
    
  271.     barcode = models.PositiveIntegerField(unique=True)
    
  272.     parent = models.ForeignKey(
    
  273.         "self", models.SET_NULL, to_field="barcode", blank=True, null=True
    
  274.     )
    
  275.     name = models.CharField(blank=False, max_length=20)
    
  276. 
    
  277.     class Meta:
    
  278.         ordering = ("name",)
    
  279. 
    
  280.     def __str__(self):
    
  281.         return self.name
    
  282. 
    
  283.     def __repr__(self):
    
  284.         return self.__str__()
    
  285. 
    
  286. 
    
  287. class Book(models.Model):
    
  288.     title = models.CharField(max_length=40)
    
  289.     author = models.ForeignKey(Writer, models.SET_NULL, blank=True, null=True)
    
  290.     special_id = models.IntegerField(blank=True, null=True, unique=True)
    
  291. 
    
  292.     class Meta:
    
  293.         unique_together = ("title", "author")
    
  294. 
    
  295. 
    
  296. class BookXtra(models.Model):
    
  297.     isbn = models.CharField(max_length=16, unique=True)
    
  298.     suffix1 = models.IntegerField(blank=True, default=0)
    
  299.     suffix2 = models.IntegerField(blank=True, default=0)
    
  300. 
    
  301.     class Meta:
    
  302.         unique_together = ("suffix1", "suffix2")
    
  303.         abstract = True
    
  304. 
    
  305. 
    
  306. class DerivedBook(Book, BookXtra):
    
  307.     pass
    
  308. 
    
  309. 
    
  310. class ExplicitPK(models.Model):
    
  311.     key = models.CharField(max_length=20, primary_key=True)
    
  312.     desc = models.CharField(max_length=20, blank=True, unique=True)
    
  313. 
    
  314.     class Meta:
    
  315.         unique_together = ("key", "desc")
    
  316. 
    
  317.     def __str__(self):
    
  318.         return self.key
    
  319. 
    
  320. 
    
  321. class Post(models.Model):
    
  322.     title = models.CharField(max_length=50, unique_for_date="posted", blank=True)
    
  323.     slug = models.CharField(max_length=50, unique_for_year="posted", blank=True)
    
  324.     subtitle = models.CharField(max_length=50, unique_for_month="posted", blank=True)
    
  325.     posted = models.DateField()
    
  326. 
    
  327.     def __str__(self):
    
  328.         return self.title
    
  329. 
    
  330. 
    
  331. class DateTimePost(models.Model):
    
  332.     title = models.CharField(max_length=50, unique_for_date="posted", blank=True)
    
  333.     slug = models.CharField(max_length=50, unique_for_year="posted", blank=True)
    
  334.     subtitle = models.CharField(max_length=50, unique_for_month="posted", blank=True)
    
  335.     posted = models.DateTimeField(editable=False)
    
  336. 
    
  337.     def __str__(self):
    
  338.         return self.title
    
  339. 
    
  340. 
    
  341. class DerivedPost(Post):
    
  342.     pass
    
  343. 
    
  344. 
    
  345. class BigInt(models.Model):
    
  346.     biggie = models.BigIntegerField()
    
  347. 
    
  348.     def __str__(self):
    
  349.         return str(self.biggie)
    
  350. 
    
  351. 
    
  352. class MarkupField(models.CharField):
    
  353.     def __init__(self, *args, **kwargs):
    
  354.         kwargs["max_length"] = 20
    
  355.         super().__init__(*args, **kwargs)
    
  356. 
    
  357.     def formfield(self, **kwargs):
    
  358.         # don't allow this field to be used in form (real use-case might be
    
  359.         # that you know the markup will always be X, but it is among an app
    
  360.         # that allows the user to say it could be something else)
    
  361.         # regressed at r10062
    
  362.         return None
    
  363. 
    
  364. 
    
  365. class CustomFieldForExclusionModel(models.Model):
    
  366.     name = models.CharField(max_length=10)
    
  367.     markup = MarkupField()
    
  368. 
    
  369. 
    
  370. class FlexibleDatePost(models.Model):
    
  371.     title = models.CharField(max_length=50, unique_for_date="posted", blank=True)
    
  372.     slug = models.CharField(max_length=50, unique_for_year="posted", blank=True)
    
  373.     subtitle = models.CharField(max_length=50, unique_for_month="posted", blank=True)
    
  374.     posted = models.DateField(blank=True, null=True)
    
  375. 
    
  376. 
    
  377. class Colour(models.Model):
    
  378.     name = models.CharField(max_length=50)
    
  379. 
    
  380.     def __iter__(self):
    
  381.         yield from range(5)
    
  382. 
    
  383.     def __str__(self):
    
  384.         return self.name
    
  385. 
    
  386. 
    
  387. class ColourfulItem(models.Model):
    
  388.     name = models.CharField(max_length=50)
    
  389.     colours = models.ManyToManyField(Colour)
    
  390. 
    
  391. 
    
  392. class CustomErrorMessage(models.Model):
    
  393.     name1 = models.CharField(
    
  394.         max_length=50,
    
  395.         validators=[validators.validate_slug],
    
  396.         error_messages={"invalid": "Model custom error message."},
    
  397.     )
    
  398.     name2 = models.CharField(
    
  399.         max_length=50,
    
  400.         validators=[validators.validate_slug],
    
  401.         error_messages={"invalid": "Model custom error message."},
    
  402.     )
    
  403. 
    
  404.     def clean(self):
    
  405.         if self.name1 == "FORBIDDEN_VALUE":
    
  406.             raise ValidationError(
    
  407.                 {"name1": [ValidationError("Model.clean() error messages.")]}
    
  408.             )
    
  409.         elif self.name1 == "FORBIDDEN_VALUE2":
    
  410.             raise ValidationError(
    
  411.                 {"name1": "Model.clean() error messages (simpler syntax)."}
    
  412.             )
    
  413.         elif self.name1 == "GLOBAL_ERROR":
    
  414.             raise ValidationError("Global error message.")
    
  415. 
    
  416. 
    
  417. def today_callable_dict():
    
  418.     return {"last_action__gte": datetime.datetime.today()}
    
  419. 
    
  420. 
    
  421. def today_callable_q():
    
  422.     return models.Q(last_action__gte=datetime.datetime.today())
    
  423. 
    
  424. 
    
  425. class Character(models.Model):
    
  426.     username = models.CharField(max_length=100)
    
  427.     last_action = models.DateTimeField()
    
  428. 
    
  429.     def __str__(self):
    
  430.         return self.username
    
  431. 
    
  432. 
    
  433. class StumpJoke(models.Model):
    
  434.     most_recently_fooled = models.ForeignKey(
    
  435.         Character,
    
  436.         models.CASCADE,
    
  437.         limit_choices_to=today_callable_dict,
    
  438.         related_name="jokes",
    
  439.     )
    
  440.     has_fooled_today = models.ManyToManyField(
    
  441.         Character,
    
  442.         limit_choices_to=today_callable_q,
    
  443.         related_name="jokes_today",
    
  444.     )
    
  445.     funny = models.BooleanField(default=False)
    
  446. 
    
  447. 
    
  448. # Model for #13776
    
  449. class Student(models.Model):
    
  450.     character = models.ForeignKey(Character, models.CASCADE)
    
  451.     study = models.CharField(max_length=30)
    
  452. 
    
  453. 
    
  454. # Model for #639
    
  455. class Photo(models.Model):
    
  456.     title = models.CharField(max_length=30)
    
  457.     image = models.FileField(storage=temp_storage, upload_to="tests")
    
  458. 
    
  459.     # Support code for the tests; this keeps track of how many times save()
    
  460.     # gets called on each instance.
    
  461.     def __init__(self, *args, **kwargs):
    
  462.         super().__init__(*args, **kwargs)
    
  463.         self._savecount = 0
    
  464. 
    
  465.     def save(self, force_insert=False, force_update=False):
    
  466.         super().save(force_insert, force_update)
    
  467.         self._savecount += 1
    
  468. 
    
  469. 
    
  470. class UUIDPK(models.Model):
    
  471.     uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
  472.     name = models.CharField(max_length=30)
    
  473. 
    
  474. 
    
  475. # Models for #24706
    
  476. class StrictAssignmentFieldSpecific(models.Model):
    
  477.     title = models.CharField(max_length=30)
    
  478.     _should_error = False
    
  479. 
    
  480.     def __setattr__(self, key, value):
    
  481.         if self._should_error is True:
    
  482.             raise ValidationError(message={key: "Cannot set attribute"}, code="invalid")
    
  483.         super().__setattr__(key, value)
    
  484. 
    
  485. 
    
  486. class StrictAssignmentAll(models.Model):
    
  487.     title = models.CharField(max_length=30)
    
  488.     _should_error = False
    
  489. 
    
  490.     def __setattr__(self, key, value):
    
  491.         if self._should_error is True:
    
  492.             raise ValidationError(message="Cannot set attribute", code="invalid")
    
  493.         super().__setattr__(key, value)
    
  494. 
    
  495. 
    
  496. # A model with ForeignKey(blank=False, null=True)
    
  497. class Award(models.Model):
    
  498.     name = models.CharField(max_length=30)
    
  499.     character = models.ForeignKey(Character, models.SET_NULL, blank=False, null=True)
    
  500. 
    
  501. 
    
  502. class NullableUniqueCharFieldModel(models.Model):
    
  503.     codename = models.CharField(max_length=50, blank=True, null=True, unique=True)
    
  504.     email = models.EmailField(blank=True, null=True)
    
  505.     slug = models.SlugField(blank=True, null=True)
    
  506.     url = models.URLField(blank=True, null=True)
    
  507. 
    
  508. 
    
  509. class Number(models.Model):
    
  510.     value = models.IntegerField()
    
  511. 
    
  512. 
    
  513. class NumbersToDice(models.Model):
    
  514.     number = models.ForeignKey("Number", on_delete=models.CASCADE)
    
  515.     die = models.ForeignKey("Dice", on_delete=models.CASCADE)
    
  516. 
    
  517. 
    
  518. class Dice(models.Model):
    
  519.     numbers = models.ManyToManyField(
    
  520.         Number,
    
  521.         through=NumbersToDice,
    
  522.         limit_choices_to=models.Q(value__gte=1),
    
  523.     )