models.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. """
  2. XX. Generating HTML forms from models
  3. This is mostly just a reworking of the ``form_for_model``/``form_for_instance``
  4. tests to use ``ModelForm``. As such, the text may not make sense in all cases,
  5. and the examples are probably a poor fit for the ``ModelForm`` syntax. In other
  6. words, most of these tests should be rewritten.
  7. """
  8. from __future__ import unicode_literals
  9. import os
  10. import tempfile
  11. from django.core.exceptions import ImproperlyConfigured
  12. from django.core.files.storage import FileSystemStorage
  13. from django.db import models
  14. from django.utils import six
  15. from django.utils.encoding import python_2_unicode_compatible
  16. from shared_models.models import Author, Book
  17. temp_storage_dir = tempfile.mkdtemp(dir=os.environ['DJANGO_TEST_TEMP_DIR'])
  18. temp_storage = FileSystemStorage(temp_storage_dir)
  19. ARTICLE_STATUS = (
  20. (1, 'Draft'),
  21. (2, 'Pending'),
  22. (3, 'Live'),
  23. )
  24. ARTICLE_STATUS_CHAR = (
  25. ('d', 'Draft'),
  26. ('p', 'Pending'),
  27. ('l', 'Live'),
  28. )
  29. @python_2_unicode_compatible
  30. class Category(models.Model):
  31. name = models.CharField(max_length=20)
  32. slug = models.SlugField(max_length=20)
  33. url = models.CharField('The URL', max_length=40)
  34. def __str__(self):
  35. return self.name
  36. def __repr__(self):
  37. return self.__str__()
  38. @python_2_unicode_compatible
  39. class Article(models.Model):
  40. headline = models.CharField(max_length=50)
  41. slug = models.SlugField()
  42. pub_date = models.DateField()
  43. created = models.DateField(editable=False)
  44. writer = models.ForeignKey(Author)
  45. article = models.TextField()
  46. categories = models.ManyToManyField(Category, blank=True)
  47. status = models.PositiveIntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
  48. def save(self):
  49. import datetime
  50. if not self.id:
  51. self.created = datetime.date.today()
  52. return super(Article, self).save()
  53. def __str__(self):
  54. return self.headline
  55. class ImprovedArticle(models.Model):
  56. article = models.OneToOneField(Article)
  57. class ImprovedArticleWithParentLink(models.Model):
  58. article = models.OneToOneField(Article, parent_link=True)
  59. class BetterAuthor(Author):
  60. score = models.IntegerField()
  61. @python_2_unicode_compatible
  62. class AuthorProfile(models.Model):
  63. writer = models.OneToOneField(Author, primary_key=True)
  64. age = models.PositiveIntegerField()
  65. def __str__(self):
  66. return "%s is %s" % (self.writer, self.age)
  67. @python_2_unicode_compatible
  68. class TextFile(models.Model):
  69. description = models.CharField(max_length=20)
  70. file = models.FileField(storage=temp_storage, upload_to='tests', max_length=15)
  71. def __str__(self):
  72. return self.description
  73. try:
  74. from django.utils.image import Image
  75. test_images = True
  76. @python_2_unicode_compatible
  77. class ImageFile(models.Model):
  78. def custom_upload_path(self, filename):
  79. path = self.path or 'tests'
  80. return '%s/%s' % (path, filename)
  81. description = models.CharField(max_length=20)
  82. # Deliberately put the image field *after* the width/height fields to
  83. # trigger the bug in #10404 with width/height not getting assigned.
  84. width = models.IntegerField(editable=False)
  85. height = models.IntegerField(editable=False)
  86. image = models.ImageField(storage=temp_storage, upload_to=custom_upload_path,
  87. width_field='width', height_field='height')
  88. path = models.CharField(max_length=16, blank=True, default='')
  89. def __str__(self):
  90. return self.description
  91. @python_2_unicode_compatible
  92. class OptionalImageFile(models.Model):
  93. def custom_upload_path(self, filename):
  94. path = self.path or 'tests'
  95. return '%s/%s' % (path, filename)
  96. description = models.CharField(max_length=20)
  97. image = models.ImageField(storage=temp_storage, upload_to=custom_upload_path,
  98. width_field='width', height_field='height',
  99. blank=True, null=True)
  100. width = models.IntegerField(editable=False, null=True)
  101. height = models.IntegerField(editable=False, null=True)
  102. path = models.CharField(max_length=16, blank=True, default='')
  103. def __str__(self):
  104. return self.description
  105. except ImproperlyConfigured:
  106. test_images = False
  107. @python_2_unicode_compatible
  108. class CommaSeparatedInteger(models.Model):
  109. field = models.CommaSeparatedIntegerField(max_length=20)
  110. def __str__(self):
  111. return self.field
  112. @python_2_unicode_compatible
  113. class Product(models.Model):
  114. slug = models.SlugField(unique=True)
  115. def __str__(self):
  116. return self.slug
  117. @python_2_unicode_compatible
  118. class Price(models.Model):
  119. price = models.DecimalField(max_digits=10, decimal_places=2)
  120. quantity = models.PositiveIntegerField()
  121. def __str__(self):
  122. return "%s for %s" % (self.quantity, self.price)
  123. class Meta:
  124. unique_together = (('price', 'quantity'),)
  125. class ArticleStatus(models.Model):
  126. status = models.CharField(max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True)
  127. @python_2_unicode_compatible
  128. class Inventory(models.Model):
  129. barcode = models.PositiveIntegerField(unique=True)
  130. parent = models.ForeignKey('self', to_field='barcode', blank=True, null=True)
  131. name = models.CharField(blank=False, max_length=20)
  132. class Meta:
  133. ordering = ('name',)
  134. def __str__(self):
  135. return self.name
  136. def __repr__(self):
  137. return self.__str__()
  138. class BookXtra(models.Model):
  139. isbn = models.CharField(max_length=16, unique=True)
  140. suffix1 = models.IntegerField(blank=True, default=0)
  141. suffix2 = models.IntegerField(blank=True, default=0)
  142. class Meta:
  143. unique_together = (('suffix1', 'suffix2'))
  144. abstract = True
  145. class DerivedBook(Book, BookXtra):
  146. pass
  147. @python_2_unicode_compatible
  148. class ExplicitPK(models.Model):
  149. key = models.CharField(max_length=20, primary_key=True)
  150. desc = models.CharField(max_length=20, blank=True, unique=True)
  151. class Meta:
  152. unique_together = ('key', 'desc')
  153. def __str__(self):
  154. return self.key
  155. @python_2_unicode_compatible
  156. class Post(models.Model):
  157. title = models.CharField(max_length=50, unique_for_date='posted', blank=True)
  158. slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
  159. subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
  160. posted = models.DateField()
  161. def __str__(self):
  162. return self.name
  163. class DerivedPost(Post):
  164. pass
  165. @python_2_unicode_compatible
  166. class BigInt(models.Model):
  167. biggie = models.BigIntegerField()
  168. def __str__(self):
  169. return six.text_type(self.biggie)
  170. class MarkupField(models.CharField):
  171. def __init__(self, *args, **kwargs):
  172. kwargs["max_length"] = 20
  173. super(MarkupField, self).__init__(*args, **kwargs)
  174. def formfield(self, **kwargs):
  175. # don't allow this field to be used in form (real use-case might be
  176. # that you know the markup will always be X, but it is among an app
  177. # that allows the user to say it could be something else)
  178. # regressed at r10062
  179. return None
  180. class CustomFieldForExclusionModel(models.Model):
  181. name = models.CharField(max_length=10)
  182. markup = MarkupField()
  183. class FlexibleDatePost(models.Model):
  184. title = models.CharField(max_length=50, unique_for_date='posted', blank=True)
  185. slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
  186. subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
  187. posted = models.DateField(blank=True, null=True)
  188. @python_2_unicode_compatible
  189. class Colour(models.Model):
  190. name = models.CharField(max_length=50)
  191. def __iter__(self):
  192. for number in xrange(5):
  193. yield number
  194. def __str__(self):
  195. return self.name
  196. class ColourfulItem(models.Model):
  197. name = models.CharField(max_length=50)
  198. colours = models.ManyToManyField(Colour)