1. ===================================
    
  2. How to write a custom storage class
    
  3. ===================================
    
  4. 
    
  5. .. currentmodule:: django.core.files.storage
    
  6. 
    
  7. If you need to provide custom file storage -- a common example is storing files
    
  8. on some remote system -- you can do so by defining a custom storage class.
    
  9. You'll need to follow these steps:
    
  10. 
    
  11. #. Your custom storage system must be a subclass of
    
  12.    ``django.core.files.storage.Storage``::
    
  13. 
    
  14.         from django.core.files.storage import Storage
    
  15. 
    
  16.         class MyStorage(Storage):
    
  17.             ...
    
  18. 
    
  19. #. Django must be able to instantiate your storage system without any arguments.
    
  20.    This means that any settings should be taken from ``django.conf.settings``::
    
  21. 
    
  22.         from django.conf import settings
    
  23.         from django.core.files.storage import Storage
    
  24. 
    
  25.         class MyStorage(Storage):
    
  26.             def __init__(self, option=None):
    
  27.                 if not option:
    
  28.                     option = settings.CUSTOM_STORAGE_OPTIONS
    
  29.                 ...
    
  30. 
    
  31. #. Your storage class must implement the :meth:`_open()` and :meth:`_save()`
    
  32.    methods, along with any other methods appropriate to your storage class. See
    
  33.    below for more on these methods.
    
  34. 
    
  35.    In addition, if your class provides local file storage, it must override
    
  36.    the ``path()`` method.
    
  37. 
    
  38. #. Your storage class must be :ref:`deconstructible <custom-deconstruct-method>`
    
  39.    so it can be serialized when it's used on a field in a migration. As long
    
  40.    as your field has arguments that are themselves
    
  41.    :ref:`serializable <migration-serializing>`, you can use the
    
  42.    ``django.utils.deconstruct.deconstructible`` class decorator for this
    
  43.    (that's what Django uses on FileSystemStorage).
    
  44. 
    
  45. By default, the following methods raise ``NotImplementedError`` and will
    
  46. typically have to be overridden:
    
  47. 
    
  48. * :meth:`Storage.delete`
    
  49. * :meth:`Storage.exists`
    
  50. * :meth:`Storage.listdir`
    
  51. * :meth:`Storage.size`
    
  52. * :meth:`Storage.url`
    
  53. 
    
  54. Note however that not all these methods are required and may be deliberately
    
  55. omitted. As it happens, it is possible to leave each method unimplemented and
    
  56. still have a working Storage.
    
  57. 
    
  58. By way of example, if listing the contents of certain storage backends turns
    
  59. out to be expensive, you might decide not to implement ``Storage.listdir()``.
    
  60. 
    
  61. Another example would be a backend that only handles writing to files. In this
    
  62. case, you would not need to implement any of the above methods.
    
  63. 
    
  64. Ultimately, which of these methods are implemented is up to you. Leaving some
    
  65. methods unimplemented will result in a partial (possibly broken) interface.
    
  66. 
    
  67. You'll also usually want to use hooks specifically designed for custom storage
    
  68. objects. These are:
    
  69. 
    
  70. .. method:: _open(name, mode='rb')
    
  71. 
    
  72. **Required**.
    
  73. 
    
  74. Called by ``Storage.open()``, this is the actual mechanism the storage class
    
  75. uses to open the file. This must return a ``File`` object, though in most cases,
    
  76. you'll want to return some subclass here that implements logic specific to the
    
  77. backend storage system.
    
  78. 
    
  79. .. method:: _save(name, content)
    
  80. 
    
  81. Called by ``Storage.save()``. The ``name`` will already have gone through
    
  82. ``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
    
  83. ``File`` object itself.
    
  84. 
    
  85. Should return the actual name of name of the file saved (usually the ``name``
    
  86. passed in, but if the storage needs to change the file name return the new name
    
  87. instead).
    
  88. 
    
  89. .. method:: get_valid_name(name)
    
  90. 
    
  91. Returns a filename suitable for use with the underlying storage system. The
    
  92. ``name`` argument passed to this method is either the original filename sent to
    
  93. the server or, if ``upload_to`` is a callable, the filename returned by that
    
  94. method after any path information is removed. Override this to customize how
    
  95. non-standard characters are converted to safe filenames.
    
  96. 
    
  97. The code provided on ``Storage`` retains only alpha-numeric characters, periods
    
  98. and underscores from the original filename, removing everything else.
    
  99. 
    
  100. .. method:: get_alternative_name(file_root, file_ext)
    
  101. 
    
  102. Returns an alternative filename based on the ``file_root`` and ``file_ext``
    
  103. parameters. By default, an underscore plus a random 7 character alphanumeric
    
  104. string is appended to the filename before the extension.
    
  105. 
    
  106. .. method:: get_available_name(name, max_length=None)
    
  107. 
    
  108. Returns a filename that is available in the storage mechanism, possibly taking
    
  109. the provided filename into account. The ``name`` argument passed to this method
    
  110. will have already cleaned to a filename valid for the storage system, according
    
  111. to the ``get_valid_name()`` method described above.
    
  112. 
    
  113. The length of the filename will not exceed ``max_length``, if provided. If a
    
  114. free unique filename cannot be found, a :exc:`SuspiciousFileOperation
    
  115. <django.core.exceptions.SuspiciousOperation>` exception is raised.
    
  116. 
    
  117. If a file with ``name`` already exists, ``get_alternative_name()`` is called to
    
  118. obtain an alternative name.