models.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. import os
  2. import tempfile
  3. import uuid
  4. from django.contrib.contenttypes.fields import (
  5. GenericForeignKey, GenericRelation,
  6. )
  7. from django.contrib.contenttypes.models import ContentType
  8. from django.core.files.storage import FileSystemStorage
  9. from django.db import models
  10. from django.db.models.fields.files import ImageField, ImageFieldFile
  11. from django.db.models.fields.related import (
  12. ForeignKey, ForeignObject, ManyToManyField, OneToOneField,
  13. )
  14. from django.utils import six
  15. try:
  16. from PIL import Image
  17. except ImportError:
  18. Image = None
  19. class Foo(models.Model):
  20. a = models.CharField(max_length=10)
  21. d = models.DecimalField(max_digits=5, decimal_places=3)
  22. def get_foo():
  23. return Foo.objects.get(id=1)
  24. class Bar(models.Model):
  25. b = models.CharField(max_length=10)
  26. a = models.ForeignKey(Foo, default=get_foo, related_name=b'bars')
  27. class Whiz(models.Model):
  28. CHOICES = (
  29. ('Group 1', (
  30. (1, 'First'),
  31. (2, 'Second'),
  32. )
  33. ),
  34. ('Group 2', (
  35. (3, 'Third'),
  36. (4, 'Fourth'),
  37. )
  38. ),
  39. (0, 'Other'),
  40. )
  41. c = models.IntegerField(choices=CHOICES, null=True)
  42. class Counter(six.Iterator):
  43. def __init__(self):
  44. self.n = 1
  45. def __iter__(self):
  46. return self
  47. def __next__(self):
  48. if self.n > 5:
  49. raise StopIteration
  50. else:
  51. self.n += 1
  52. return (self.n, 'val-' + str(self.n))
  53. class WhizIter(models.Model):
  54. c = models.IntegerField(choices=Counter(), null=True)
  55. class WhizIterEmpty(models.Model):
  56. c = models.CharField(choices=(x for x in []), blank=True, max_length=1)
  57. class BigD(models.Model):
  58. d = models.DecimalField(max_digits=38, decimal_places=30)
  59. class FloatModel(models.Model):
  60. size = models.FloatField()
  61. class BigS(models.Model):
  62. s = models.SlugField(max_length=255)
  63. class SmallIntegerModel(models.Model):
  64. value = models.SmallIntegerField()
  65. class IntegerModel(models.Model):
  66. value = models.IntegerField()
  67. class BigIntegerModel(models.Model):
  68. value = models.BigIntegerField()
  69. null_value = models.BigIntegerField(null=True, blank=True)
  70. class PositiveSmallIntegerModel(models.Model):
  71. value = models.PositiveSmallIntegerField()
  72. class PositiveIntegerModel(models.Model):
  73. value = models.PositiveIntegerField()
  74. class Post(models.Model):
  75. title = models.CharField(max_length=100)
  76. body = models.TextField()
  77. class NullBooleanModel(models.Model):
  78. nbfield = models.NullBooleanField()
  79. class BooleanModel(models.Model):
  80. bfield = models.BooleanField(default=None)
  81. string = models.CharField(max_length=10, default='abc')
  82. class DateTimeModel(models.Model):
  83. d = models.DateField()
  84. dt = models.DateTimeField()
  85. t = models.TimeField()
  86. class DurationModel(models.Model):
  87. field = models.DurationField()
  88. class NullDurationModel(models.Model):
  89. field = models.DurationField(null=True)
  90. class PrimaryKeyCharModel(models.Model):
  91. string = models.CharField(max_length=10, primary_key=True)
  92. class FksToBooleans(models.Model):
  93. """Model with FKs to models with {Null,}BooleanField's, #15040"""
  94. bf = models.ForeignKey(BooleanModel)
  95. nbf = models.ForeignKey(NullBooleanModel)
  96. class FkToChar(models.Model):
  97. """Model with FK to a model with a CharField primary key, #19299"""
  98. out = models.ForeignKey(PrimaryKeyCharModel)
  99. class RenamedField(models.Model):
  100. modelname = models.IntegerField(name="fieldname", choices=((1, 'One'),))
  101. class VerboseNameField(models.Model):
  102. id = models.AutoField("verbose pk", primary_key=True)
  103. field1 = models.BigIntegerField("verbose field1")
  104. field2 = models.BooleanField("verbose field2", default=False)
  105. field3 = models.CharField("verbose field3", max_length=10)
  106. field4 = models.CommaSeparatedIntegerField("verbose field4", max_length=99)
  107. field5 = models.DateField("verbose field5")
  108. field6 = models.DateTimeField("verbose field6")
  109. field7 = models.DecimalField("verbose field7", max_digits=6, decimal_places=1)
  110. field8 = models.EmailField("verbose field8")
  111. field9 = models.FileField("verbose field9", upload_to="unused")
  112. field10 = models.FilePathField("verbose field10")
  113. field11 = models.FloatField("verbose field11")
  114. # Don't want to depend on Pillow in this test
  115. # field_image = models.ImageField("verbose field")
  116. field12 = models.IntegerField("verbose field12")
  117. field13 = models.GenericIPAddressField("verbose field13", protocol="ipv4")
  118. field14 = models.NullBooleanField("verbose field14")
  119. field15 = models.PositiveIntegerField("verbose field15")
  120. field16 = models.PositiveSmallIntegerField("verbose field16")
  121. field17 = models.SlugField("verbose field17")
  122. field18 = models.SmallIntegerField("verbose field18")
  123. field19 = models.TextField("verbose field19")
  124. field20 = models.TimeField("verbose field20")
  125. field21 = models.URLField("verbose field21")
  126. field22 = models.UUIDField("verbose field22")
  127. field23 = models.DurationField("verbose field23")
  128. class GenericIPAddress(models.Model):
  129. ip = models.GenericIPAddressField(null=True, protocol='ipv4')
  130. ###############################################################################
  131. # These models aren't used in any test, just here to ensure they validate
  132. # successfully.
  133. # See ticket #16570.
  134. class DecimalLessThanOne(models.Model):
  135. d = models.DecimalField(max_digits=3, decimal_places=3)
  136. # See ticket #18389.
  137. class FieldClassAttributeModel(models.Model):
  138. field_class = models.CharField
  139. ###############################################################################
  140. class DataModel(models.Model):
  141. short_data = models.BinaryField(max_length=10, default=b'\x08')
  142. data = models.BinaryField()
  143. ###############################################################################
  144. # FileField
  145. class Document(models.Model):
  146. myfile = models.FileField(upload_to='unused')
  147. ###############################################################################
  148. # ImageField
  149. # If Pillow available, do these tests.
  150. if Image:
  151. class TestImageFieldFile(ImageFieldFile):
  152. """
  153. Custom Field File class that records whether or not the underlying file
  154. was opened.
  155. """
  156. def __init__(self, *args, **kwargs):
  157. self.was_opened = False
  158. super(TestImageFieldFile, self).__init__(*args, **kwargs)
  159. def open(self):
  160. self.was_opened = True
  161. super(TestImageFieldFile, self).open()
  162. class TestImageField(ImageField):
  163. attr_class = TestImageFieldFile
  164. # Set up a temp directory for file storage.
  165. temp_storage_dir = tempfile.mkdtemp(dir=os.environ['DJANGO_TEST_TEMP_DIR'])
  166. temp_storage = FileSystemStorage(temp_storage_dir)
  167. temp_upload_to_dir = os.path.join(temp_storage.location, 'tests')
  168. class Person(models.Model):
  169. """
  170. Model that defines an ImageField with no dimension fields.
  171. """
  172. name = models.CharField(max_length=50)
  173. mugshot = TestImageField(storage=temp_storage, upload_to='tests')
  174. class AbsctractPersonWithHeight(models.Model):
  175. """
  176. Abstract model that defines an ImageField with only one dimension field
  177. to make sure the dimension update is correctly run on concrete subclass
  178. instance post-initialization.
  179. """
  180. mugshot = TestImageField(storage=temp_storage, upload_to='tests',
  181. height_field='mugshot_height')
  182. mugshot_height = models.PositiveSmallIntegerField()
  183. class Meta:
  184. abstract = True
  185. class PersonWithHeight(AbsctractPersonWithHeight):
  186. """
  187. Concrete model that subclass an abctract one with only on dimension
  188. field.
  189. """
  190. name = models.CharField(max_length=50)
  191. class PersonWithHeightAndWidth(models.Model):
  192. """
  193. Model that defines height and width fields after the ImageField.
  194. """
  195. name = models.CharField(max_length=50)
  196. mugshot = TestImageField(storage=temp_storage, upload_to='tests',
  197. height_field='mugshot_height',
  198. width_field='mugshot_width')
  199. mugshot_height = models.PositiveSmallIntegerField()
  200. mugshot_width = models.PositiveSmallIntegerField()
  201. class PersonDimensionsFirst(models.Model):
  202. """
  203. Model that defines height and width fields before the ImageField.
  204. """
  205. name = models.CharField(max_length=50)
  206. mugshot_height = models.PositiveSmallIntegerField()
  207. mugshot_width = models.PositiveSmallIntegerField()
  208. mugshot = TestImageField(storage=temp_storage, upload_to='tests',
  209. height_field='mugshot_height',
  210. width_field='mugshot_width')
  211. class PersonTwoImages(models.Model):
  212. """
  213. Model that:
  214. * Defines two ImageFields
  215. * Defines the height/width fields before the ImageFields
  216. * Has a nullalble ImageField
  217. """
  218. name = models.CharField(max_length=50)
  219. mugshot_height = models.PositiveSmallIntegerField()
  220. mugshot_width = models.PositiveSmallIntegerField()
  221. mugshot = TestImageField(storage=temp_storage, upload_to='tests',
  222. height_field='mugshot_height',
  223. width_field='mugshot_width')
  224. headshot_height = models.PositiveSmallIntegerField(
  225. blank=True, null=True)
  226. headshot_width = models.PositiveSmallIntegerField(
  227. blank=True, null=True)
  228. headshot = TestImageField(blank=True, null=True,
  229. storage=temp_storage, upload_to='tests',
  230. height_field='headshot_height',
  231. width_field='headshot_width')
  232. class AllFieldsModel(models.Model):
  233. big_integer = models.BigIntegerField()
  234. binary = models.BinaryField()
  235. boolean = models.BooleanField(default=False)
  236. char = models.CharField(max_length=10)
  237. csv = models.CommaSeparatedIntegerField(max_length=10)
  238. date = models.DateField()
  239. datetime = models.DateTimeField()
  240. decimal = models.DecimalField(decimal_places=2, max_digits=2)
  241. duration = models.DurationField()
  242. email = models.EmailField()
  243. file_path = models.FilePathField()
  244. floatf = models.FloatField()
  245. integer = models.IntegerField()
  246. generic_ip = models.GenericIPAddressField()
  247. null_boolean = models.NullBooleanField()
  248. positive_integer = models.PositiveIntegerField()
  249. positive_small_integer = models.PositiveSmallIntegerField()
  250. slug = models.SlugField()
  251. small_integer = models.SmallIntegerField()
  252. text = models.TextField()
  253. time = models.TimeField()
  254. url = models.URLField()
  255. uuid = models.UUIDField()
  256. fo = ForeignObject(
  257. 'self',
  258. from_fields=['abstract_non_concrete_id'],
  259. to_fields=['id'],
  260. related_name='reverse'
  261. )
  262. fk = ForeignKey(
  263. 'self',
  264. related_name='reverse2'
  265. )
  266. m2m = ManyToManyField('self')
  267. oto = OneToOneField('self')
  268. object_id = models.PositiveIntegerField()
  269. content_type = models.ForeignKey(ContentType)
  270. gfk = GenericForeignKey()
  271. gr = GenericRelation(DataModel)
  272. ###############################################################################
  273. class UUIDModel(models.Model):
  274. field = models.UUIDField()
  275. class NullableUUIDModel(models.Model):
  276. field = models.UUIDField(blank=True, null=True)
  277. class PrimaryKeyUUIDModel(models.Model):
  278. id = models.UUIDField(primary_key=True, default=uuid.uuid4)
  279. class RelatedToUUIDModel(models.Model):
  280. uuid_fk = models.ForeignKey('PrimaryKeyUUIDModel')
  281. ###############################################################################
  282. # See ticket #24215.
  283. class AbstractForeignFieldsModel(models.Model):
  284. fk = models.ForeignKey('missing.FK')
  285. m2m = models.ManyToManyField('missing.M2M', through='missing.Through')
  286. class Meta:
  287. abstract = True