2
0

models.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. """
  2. 42. Storing files according to a custom storage system
  3. ``FileField`` and its variations can take a ``storage`` argument to specify how
  4. and where files should be stored.
  5. """
  6. import random
  7. import tempfile
  8. from django.db import models
  9. from django.core.files.base import ContentFile
  10. from django.core.files.storage import FileSystemStorage
  11. temp_storage_location = tempfile.mkdtemp()
  12. temp_storage = FileSystemStorage(location=temp_storage_location)
  13. # Write out a file to be used as default content
  14. temp_storage.save('tests/default.txt', ContentFile('default content'))
  15. class Storage(models.Model):
  16. def custom_upload_to(self, filename):
  17. return 'foo'
  18. def random_upload_to(self, filename):
  19. # This returns a different result each time,
  20. # to make sure it only gets called once.
  21. return '%s/%s' % (random.randint(100, 999), filename)
  22. normal = models.FileField(storage=temp_storage, upload_to='tests')
  23. custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
  24. random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
  25. default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')
  26. __test__ = {'API_TESTS':"""
  27. # Attempting to access a FileField from the class raises a descriptive error
  28. >>> Storage.normal
  29. Traceback (most recent call last):
  30. ...
  31. AttributeError: The 'normal' attribute can only be accessed from Storage instances.
  32. # An object without a file has limited functionality.
  33. >>> obj1 = Storage()
  34. >>> obj1.normal
  35. <FieldFile: None>
  36. >>> obj1.normal.size
  37. Traceback (most recent call last):
  38. ...
  39. ValueError: The 'normal' attribute has no file associated with it.
  40. # Saving a file enables full functionality.
  41. >>> obj1.normal.save('django_test.txt', ContentFile('content'))
  42. >>> obj1.normal
  43. <FieldFile: tests/django_test.txt>
  44. >>> obj1.normal.size
  45. 7
  46. >>> obj1.normal.read()
  47. 'content'
  48. # File objects can be assigned to FileField attributes, but shouldn't get
  49. # committed until the model it's attached to is saved.
  50. >>> from django.core.files.uploadedfile import SimpleUploadedFile
  51. >>> obj1.normal = SimpleUploadedFile('assignment.txt', 'content')
  52. >>> dirs, files = temp_storage.listdir('tests')
  53. >>> dirs
  54. []
  55. >>> files.sort()
  56. >>> files
  57. ['default.txt', 'django_test.txt']
  58. >>> obj1.save()
  59. >>> dirs, files = temp_storage.listdir('tests')
  60. >>> files.sort()
  61. >>> files
  62. ['assignment.txt', 'default.txt', 'django_test.txt']
  63. # Files can be read in a little at a time, if necessary.
  64. >>> obj1.normal.open()
  65. >>> obj1.normal.read(3)
  66. 'con'
  67. >>> obj1.normal.read()
  68. 'tent'
  69. >>> '-'.join(obj1.normal.chunks(chunk_size=2))
  70. 'co-nt-en-t'
  71. # Save another file with the same name.
  72. >>> obj2 = Storage()
  73. >>> obj2.normal.save('django_test.txt', ContentFile('more content'))
  74. >>> obj2.normal
  75. <FieldFile: tests/django_test_1.txt>
  76. >>> obj2.normal.size
  77. 12
  78. # Push the objects into the cache to make sure they pickle properly
  79. >>> from django.core.cache import cache
  80. >>> cache.set('obj1', obj1)
  81. >>> cache.set('obj2', obj2)
  82. >>> cache.get('obj2').normal
  83. <FieldFile: tests/django_test_1.txt>
  84. # Deleting an object deletes the file it uses, if there are no other objects
  85. # still using that file.
  86. >>> obj2.delete()
  87. >>> obj2.normal.save('django_test.txt', ContentFile('more content'))
  88. >>> obj2.normal
  89. <FieldFile: tests/django_test_1.txt>
  90. # Multiple files with the same name get _N appended to them.
  91. >>> objs = [Storage() for i in range(3)]
  92. >>> for o in objs:
  93. ... o.normal.save('multiple_files.txt', ContentFile('Same Content'))
  94. >>> [o.normal for o in objs]
  95. [<FieldFile: tests/multiple_files.txt>, <FieldFile: tests/multiple_files_1.txt>, <FieldFile: tests/multiple_files_2.txt>]
  96. >>> for o in objs:
  97. ... o.delete()
  98. # Default values allow an object to access a single file.
  99. >>> obj3 = Storage.objects.create()
  100. >>> obj3.default
  101. <FieldFile: tests/default.txt>
  102. >>> obj3.default.read()
  103. 'default content'
  104. # But it shouldn't be deleted, even if there are no more objects using it.
  105. >>> obj3.delete()
  106. >>> obj3 = Storage()
  107. >>> obj3.default.read()
  108. 'default content'
  109. # Verify the fix for #5655, making sure the directory is only determined once.
  110. >>> obj4 = Storage()
  111. >>> obj4.random.save('random_file', ContentFile('random content'))
  112. >>> obj4.random
  113. <FieldFile: .../random_file>
  114. # Clean up the temporary files and dir.
  115. >>> obj1.normal.delete()
  116. >>> obj2.normal.delete()
  117. >>> obj3.default.delete()
  118. >>> obj4.random.delete()
  119. >>> import shutil
  120. >>> shutil.rmtree(temp_storage_location)
  121. """}