1. import json
    
  2. import os
    
  3. import tempfile
    
  4. import uuid
    
  5. 
    
  6. from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    
  7. from django.contrib.contenttypes.models import ContentType
    
  8. from django.core.files.storage import FileSystemStorage
    
  9. from django.core.serializers.json import DjangoJSONEncoder
    
  10. from django.db import models
    
  11. from django.db.models.fields.files import ImageFieldFile
    
  12. from django.utils.translation import gettext_lazy as _
    
  13. 
    
  14. try:
    
  15.     from PIL import Image
    
  16. except ImportError:
    
  17.     Image = None
    
  18. 
    
  19. 
    
  20. class Foo(models.Model):
    
  21.     a = models.CharField(max_length=10)
    
  22.     d = models.DecimalField(max_digits=5, decimal_places=3)
    
  23. 
    
  24. 
    
  25. def get_foo():
    
  26.     return Foo.objects.get(id=1).pk
    
  27. 
    
  28. 
    
  29. class Bar(models.Model):
    
  30.     b = models.CharField(max_length=10)
    
  31.     a = models.ForeignKey(Foo, models.CASCADE, default=get_foo, related_name="bars")
    
  32. 
    
  33. 
    
  34. class Whiz(models.Model):
    
  35.     CHOICES = (
    
  36.         (
    
  37.             "Group 1",
    
  38.             (
    
  39.                 (1, "First"),
    
  40.                 (2, "Second"),
    
  41.             ),
    
  42.         ),
    
  43.         (
    
  44.             "Group 2",
    
  45.             (
    
  46.                 (3, "Third"),
    
  47.                 (4, "Fourth"),
    
  48.             ),
    
  49.         ),
    
  50.         (0, "Other"),
    
  51.         (5, _("translated")),
    
  52.     )
    
  53.     c = models.IntegerField(choices=CHOICES, null=True)
    
  54. 
    
  55. 
    
  56. class WhizDelayed(models.Model):
    
  57.     c = models.IntegerField(choices=(), null=True)
    
  58. 
    
  59. 
    
  60. # Contrived way of adding choices later.
    
  61. WhizDelayed._meta.get_field("c").choices = Whiz.CHOICES
    
  62. 
    
  63. 
    
  64. class WhizIter(models.Model):
    
  65.     c = models.IntegerField(choices=iter(Whiz.CHOICES), null=True)
    
  66. 
    
  67. 
    
  68. class WhizIterEmpty(models.Model):
    
  69.     c = models.CharField(choices=iter(()), blank=True, max_length=1)
    
  70. 
    
  71. 
    
  72. class Choiceful(models.Model):
    
  73.     no_choices = models.IntegerField(null=True)
    
  74.     empty_choices = models.IntegerField(choices=(), null=True)
    
  75.     with_choices = models.IntegerField(choices=[(1, "A")], null=True)
    
  76.     empty_choices_bool = models.BooleanField(choices=())
    
  77.     empty_choices_text = models.TextField(choices=())
    
  78. 
    
  79. 
    
  80. class BigD(models.Model):
    
  81.     d = models.DecimalField(max_digits=32, decimal_places=30)
    
  82. 
    
  83. 
    
  84. class FloatModel(models.Model):
    
  85.     size = models.FloatField()
    
  86. 
    
  87. 
    
  88. class BigS(models.Model):
    
  89.     s = models.SlugField(max_length=255)
    
  90. 
    
  91. 
    
  92. class UnicodeSlugField(models.Model):
    
  93.     s = models.SlugField(max_length=255, allow_unicode=True)
    
  94. 
    
  95. 
    
  96. class AutoModel(models.Model):
    
  97.     value = models.AutoField(primary_key=True)
    
  98. 
    
  99. 
    
  100. class BigAutoModel(models.Model):
    
  101.     value = models.BigAutoField(primary_key=True)
    
  102. 
    
  103. 
    
  104. class SmallAutoModel(models.Model):
    
  105.     value = models.SmallAutoField(primary_key=True)
    
  106. 
    
  107. 
    
  108. class SmallIntegerModel(models.Model):
    
  109.     value = models.SmallIntegerField()
    
  110. 
    
  111. 
    
  112. class IntegerModel(models.Model):
    
  113.     value = models.IntegerField()
    
  114. 
    
  115. 
    
  116. class BigIntegerModel(models.Model):
    
  117.     value = models.BigIntegerField()
    
  118.     null_value = models.BigIntegerField(null=True, blank=True)
    
  119. 
    
  120. 
    
  121. class PositiveBigIntegerModel(models.Model):
    
  122.     value = models.PositiveBigIntegerField()
    
  123. 
    
  124. 
    
  125. class PositiveSmallIntegerModel(models.Model):
    
  126.     value = models.PositiveSmallIntegerField()
    
  127. 
    
  128. 
    
  129. class PositiveIntegerModel(models.Model):
    
  130.     value = models.PositiveIntegerField()
    
  131. 
    
  132. 
    
  133. class Post(models.Model):
    
  134.     title = models.CharField(max_length=100)
    
  135.     body = models.TextField()
    
  136. 
    
  137. 
    
  138. class NullBooleanModel(models.Model):
    
  139.     nbfield = models.BooleanField(null=True, blank=True)
    
  140. 
    
  141. 
    
  142. class BooleanModel(models.Model):
    
  143.     bfield = models.BooleanField()
    
  144.     string = models.CharField(max_length=10, default="abc")
    
  145. 
    
  146. 
    
  147. class DateTimeModel(models.Model):
    
  148.     d = models.DateField()
    
  149.     dt = models.DateTimeField()
    
  150.     t = models.TimeField()
    
  151. 
    
  152. 
    
  153. class DurationModel(models.Model):
    
  154.     field = models.DurationField()
    
  155. 
    
  156. 
    
  157. class NullDurationModel(models.Model):
    
  158.     field = models.DurationField(null=True)
    
  159. 
    
  160. 
    
  161. class PrimaryKeyCharModel(models.Model):
    
  162.     string = models.CharField(max_length=10, primary_key=True)
    
  163. 
    
  164. 
    
  165. class FksToBooleans(models.Model):
    
  166.     """Model with FKs to models with {Null,}BooleanField's, #15040"""
    
  167. 
    
  168.     bf = models.ForeignKey(BooleanModel, models.CASCADE)
    
  169.     nbf = models.ForeignKey(NullBooleanModel, models.CASCADE)
    
  170. 
    
  171. 
    
  172. class FkToChar(models.Model):
    
  173.     """Model with FK to a model with a CharField primary key, #19299"""
    
  174. 
    
  175.     out = models.ForeignKey(PrimaryKeyCharModel, models.CASCADE)
    
  176. 
    
  177. 
    
  178. class RenamedField(models.Model):
    
  179.     modelname = models.IntegerField(name="fieldname", choices=((1, "One"),))
    
  180. 
    
  181. 
    
  182. class VerboseNameField(models.Model):
    
  183.     id = models.AutoField("verbose pk", primary_key=True)
    
  184.     field1 = models.BigIntegerField("verbose field1")
    
  185.     field2 = models.BooleanField("verbose field2", default=False)
    
  186.     field3 = models.CharField("verbose field3", max_length=10)
    
  187.     field4 = models.DateField("verbose field4")
    
  188.     field5 = models.DateTimeField("verbose field5")
    
  189.     field6 = models.DecimalField("verbose field6", max_digits=6, decimal_places=1)
    
  190.     field7 = models.EmailField("verbose field7")
    
  191.     field8 = models.FileField("verbose field8", upload_to="unused")
    
  192.     field9 = models.FilePathField("verbose field9")
    
  193.     field10 = models.FloatField("verbose field10")
    
  194.     # Don't want to depend on Pillow in this test
    
  195.     # field_image = models.ImageField("verbose field")
    
  196.     field11 = models.IntegerField("verbose field11")
    
  197.     field12 = models.GenericIPAddressField("verbose field12", protocol="ipv4")
    
  198.     field13 = models.PositiveIntegerField("verbose field13")
    
  199.     field14 = models.PositiveSmallIntegerField("verbose field14")
    
  200.     field15 = models.SlugField("verbose field15")
    
  201.     field16 = models.SmallIntegerField("verbose field16")
    
  202.     field17 = models.TextField("verbose field17")
    
  203.     field18 = models.TimeField("verbose field18")
    
  204.     field19 = models.URLField("verbose field19")
    
  205.     field20 = models.UUIDField("verbose field20")
    
  206.     field21 = models.DurationField("verbose field21")
    
  207. 
    
  208. 
    
  209. class GenericIPAddress(models.Model):
    
  210.     ip = models.GenericIPAddressField(null=True, protocol="ipv4")
    
  211. 
    
  212. 
    
  213. ###############################################################################
    
  214. # These models aren't used in any test, just here to ensure they validate
    
  215. # successfully.
    
  216. 
    
  217. 
    
  218. # See ticket #16570.
    
  219. class DecimalLessThanOne(models.Model):
    
  220.     d = models.DecimalField(max_digits=3, decimal_places=3)
    
  221. 
    
  222. 
    
  223. # See ticket #18389.
    
  224. class FieldClassAttributeModel(models.Model):
    
  225.     field_class = models.CharField
    
  226. 
    
  227. 
    
  228. ###############################################################################
    
  229. 
    
  230. 
    
  231. class DataModel(models.Model):
    
  232.     short_data = models.BinaryField(max_length=10, default=b"\x08")
    
  233.     data = models.BinaryField()
    
  234. 
    
  235. 
    
  236. ###############################################################################
    
  237. # FileField
    
  238. 
    
  239. 
    
  240. class Document(models.Model):
    
  241.     myfile = models.FileField(upload_to="unused", unique=True)
    
  242. 
    
  243. 
    
  244. ###############################################################################
    
  245. # ImageField
    
  246. 
    
  247. # If Pillow available, do these tests.
    
  248. if Image:
    
  249. 
    
  250.     class TestImageFieldFile(ImageFieldFile):
    
  251.         """
    
  252.         Custom Field File class that records whether or not the underlying file
    
  253.         was opened.
    
  254.         """
    
  255. 
    
  256.         def __init__(self, *args, **kwargs):
    
  257.             self.was_opened = False
    
  258.             super().__init__(*args, **kwargs)
    
  259. 
    
  260.         def open(self):
    
  261.             self.was_opened = True
    
  262.             super().open()
    
  263. 
    
  264.     class TestImageField(models.ImageField):
    
  265.         attr_class = TestImageFieldFile
    
  266. 
    
  267.     # Set up a temp directory for file storage.
    
  268.     temp_storage_dir = tempfile.mkdtemp()
    
  269.     temp_storage = FileSystemStorage(temp_storage_dir)
    
  270.     temp_upload_to_dir = os.path.join(temp_storage.location, "tests")
    
  271. 
    
  272.     class Person(models.Model):
    
  273.         """
    
  274.         Model that defines an ImageField with no dimension fields.
    
  275.         """
    
  276. 
    
  277.         name = models.CharField(max_length=50)
    
  278.         mugshot = TestImageField(storage=temp_storage, upload_to="tests")
    
  279. 
    
  280.     class AbstractPersonWithHeight(models.Model):
    
  281.         """
    
  282.         Abstract model that defines an ImageField with only one dimension field
    
  283.         to make sure the dimension update is correctly run on concrete subclass
    
  284.         instance post-initialization.
    
  285.         """
    
  286. 
    
  287.         mugshot = TestImageField(
    
  288.             storage=temp_storage, upload_to="tests", height_field="mugshot_height"
    
  289.         )
    
  290.         mugshot_height = models.PositiveSmallIntegerField()
    
  291. 
    
  292.         class Meta:
    
  293.             abstract = True
    
  294. 
    
  295.     class PersonWithHeight(AbstractPersonWithHeight):
    
  296.         """
    
  297.         Concrete model that subclass an abstract one with only on dimension
    
  298.         field.
    
  299.         """
    
  300. 
    
  301.         name = models.CharField(max_length=50)
    
  302. 
    
  303.     class PersonWithHeightAndWidth(models.Model):
    
  304.         """
    
  305.         Model that defines height and width fields after the ImageField.
    
  306.         """
    
  307. 
    
  308.         name = models.CharField(max_length=50)
    
  309.         mugshot = TestImageField(
    
  310.             storage=temp_storage,
    
  311.             upload_to="tests",
    
  312.             height_field="mugshot_height",
    
  313.             width_field="mugshot_width",
    
  314.         )
    
  315.         mugshot_height = models.PositiveSmallIntegerField()
    
  316.         mugshot_width = models.PositiveSmallIntegerField()
    
  317. 
    
  318.     class PersonDimensionsFirst(models.Model):
    
  319.         """
    
  320.         Model that defines height and width fields before the ImageField.
    
  321.         """
    
  322. 
    
  323.         name = models.CharField(max_length=50)
    
  324.         mugshot_height = models.PositiveSmallIntegerField()
    
  325.         mugshot_width = models.PositiveSmallIntegerField()
    
  326.         mugshot = TestImageField(
    
  327.             storage=temp_storage,
    
  328.             upload_to="tests",
    
  329.             height_field="mugshot_height",
    
  330.             width_field="mugshot_width",
    
  331.         )
    
  332. 
    
  333.     class PersonTwoImages(models.Model):
    
  334.         """
    
  335.         Model that:
    
  336.         * Defines two ImageFields
    
  337.         * Defines the height/width fields before the ImageFields
    
  338.         * Has a nullable ImageField
    
  339.         """
    
  340. 
    
  341.         name = models.CharField(max_length=50)
    
  342.         mugshot_height = models.PositiveSmallIntegerField()
    
  343.         mugshot_width = models.PositiveSmallIntegerField()
    
  344.         mugshot = TestImageField(
    
  345.             storage=temp_storage,
    
  346.             upload_to="tests",
    
  347.             height_field="mugshot_height",
    
  348.             width_field="mugshot_width",
    
  349.         )
    
  350.         headshot_height = models.PositiveSmallIntegerField(blank=True, null=True)
    
  351.         headshot_width = models.PositiveSmallIntegerField(blank=True, null=True)
    
  352.         headshot = TestImageField(
    
  353.             blank=True,
    
  354.             null=True,
    
  355.             storage=temp_storage,
    
  356.             upload_to="tests",
    
  357.             height_field="headshot_height",
    
  358.             width_field="headshot_width",
    
  359.         )
    
  360. 
    
  361. 
    
  362. class CustomJSONDecoder(json.JSONDecoder):
    
  363.     def __init__(self, object_hook=None, *args, **kwargs):
    
  364.         return super().__init__(object_hook=self.as_uuid, *args, **kwargs)
    
  365. 
    
  366.     def as_uuid(self, dct):
    
  367.         if "uuid" in dct:
    
  368.             dct["uuid"] = uuid.UUID(dct["uuid"])
    
  369.         return dct
    
  370. 
    
  371. 
    
  372. class JSONModel(models.Model):
    
  373.     value = models.JSONField()
    
  374. 
    
  375.     class Meta:
    
  376.         required_db_features = {"supports_json_field"}
    
  377. 
    
  378. 
    
  379. class NullableJSONModel(models.Model):
    
  380.     value = models.JSONField(blank=True, null=True)
    
  381.     value_custom = models.JSONField(
    
  382.         encoder=DjangoJSONEncoder,
    
  383.         decoder=CustomJSONDecoder,
    
  384.         null=True,
    
  385.     )
    
  386. 
    
  387.     class Meta:
    
  388.         required_db_features = {"supports_json_field"}
    
  389. 
    
  390. 
    
  391. class RelatedJSONModel(models.Model):
    
  392.     value = models.JSONField()
    
  393.     json_model = models.ForeignKey(NullableJSONModel, models.CASCADE)
    
  394. 
    
  395.     class Meta:
    
  396.         required_db_features = {"supports_json_field"}
    
  397. 
    
  398. 
    
  399. class AllFieldsModel(models.Model):
    
  400.     big_integer = models.BigIntegerField()
    
  401.     binary = models.BinaryField()
    
  402.     boolean = models.BooleanField(default=False)
    
  403.     char = models.CharField(max_length=10)
    
  404.     date = models.DateField()
    
  405.     datetime = models.DateTimeField()
    
  406.     decimal = models.DecimalField(decimal_places=2, max_digits=2)
    
  407.     duration = models.DurationField()
    
  408.     email = models.EmailField()
    
  409.     file_path = models.FilePathField()
    
  410.     floatf = models.FloatField()
    
  411.     integer = models.IntegerField()
    
  412.     generic_ip = models.GenericIPAddressField()
    
  413.     positive_integer = models.PositiveIntegerField()
    
  414.     positive_small_integer = models.PositiveSmallIntegerField()
    
  415.     slug = models.SlugField()
    
  416.     small_integer = models.SmallIntegerField()
    
  417.     text = models.TextField()
    
  418.     time = models.TimeField()
    
  419.     url = models.URLField()
    
  420.     uuid = models.UUIDField()
    
  421. 
    
  422.     fo = models.ForeignObject(
    
  423.         "self",
    
  424.         on_delete=models.CASCADE,
    
  425.         from_fields=["positive_integer"],
    
  426.         to_fields=["id"],
    
  427.         related_name="reverse",
    
  428.     )
    
  429.     fk = models.ForeignKey("self", models.CASCADE, related_name="reverse2")
    
  430.     m2m = models.ManyToManyField("self")
    
  431.     oto = models.OneToOneField("self", models.CASCADE)
    
  432. 
    
  433.     object_id = models.PositiveIntegerField()
    
  434.     content_type = models.ForeignKey(ContentType, models.CASCADE)
    
  435.     gfk = GenericForeignKey()
    
  436.     gr = GenericRelation(DataModel)
    
  437. 
    
  438. 
    
  439. class ManyToMany(models.Model):
    
  440.     m2m = models.ManyToManyField("self")
    
  441. 
    
  442. 
    
  443. ###############################################################################
    
  444. 
    
  445. 
    
  446. class UUIDModel(models.Model):
    
  447.     field = models.UUIDField()
    
  448. 
    
  449. 
    
  450. class NullableUUIDModel(models.Model):
    
  451.     field = models.UUIDField(blank=True, null=True)
    
  452. 
    
  453. 
    
  454. class PrimaryKeyUUIDModel(models.Model):
    
  455.     id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    
  456. 
    
  457. 
    
  458. class RelatedToUUIDModel(models.Model):
    
  459.     uuid_fk = models.ForeignKey("PrimaryKeyUUIDModel", models.CASCADE)
    
  460. 
    
  461. 
    
  462. class UUIDChild(PrimaryKeyUUIDModel):
    
  463.     pass
    
  464. 
    
  465. 
    
  466. class UUIDGrandchild(UUIDChild):
    
  467.     pass