2021-07-13 07:25:37 +00:00
|
|
|
===================================
|
|
|
|
How to write a custom storage class
|
|
|
|
===================================
|
2008-08-23 22:25:40 +00:00
|
|
|
|
2008-09-03 20:27:54 +00:00
|
|
|
.. currentmodule:: django.core.files.storage
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
If you need to provide custom file storage -- a common example is storing files
|
|
|
|
on some remote system -- you can do so by defining a custom storage class.
|
|
|
|
You'll need to follow these steps:
|
|
|
|
|
|
|
|
#. Your custom storage system must be a subclass of
|
|
|
|
``django.core.files.storage.Storage``::
|
|
|
|
|
|
|
|
from django.core.files.storage import Storage
|
|
|
|
|
2023-03-01 12:35:43 +00:00
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
class MyStorage(Storage):
|
|
|
|
...
|
|
|
|
|
|
|
|
#. Django must be able to instantiate your storage system without any arguments.
|
|
|
|
This means that any settings should be taken from ``django.conf.settings``::
|
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
from django.core.files.storage import Storage
|
|
|
|
|
2023-03-01 12:35:43 +00:00
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
class MyStorage(Storage):
|
|
|
|
def __init__(self, option=None):
|
|
|
|
if not option:
|
|
|
|
option = settings.CUSTOM_STORAGE_OPTIONS
|
|
|
|
...
|
|
|
|
|
2012-11-17 22:25:37 +00:00
|
|
|
#. Your storage class must implement the :meth:`_open()` and :meth:`_save()`
|
2012-11-17 15:05:34 +00:00
|
|
|
methods, along with any other methods appropriate to your storage class. See
|
|
|
|
below for more on these methods.
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
|
|
In addition, if your class provides local file storage, it must override
|
|
|
|
the ``path()`` method.
|
|
|
|
|
2014-05-07 06:06:41 +00:00
|
|
|
#. Your storage class must be :ref:`deconstructible <custom-deconstruct-method>`
|
|
|
|
so it can be serialized when it's used on a field in a migration. As long
|
|
|
|
as your field has arguments that are themselves
|
|
|
|
:ref:`serializable <migration-serializing>`, you can use the
|
|
|
|
``django.utils.deconstruct.deconstructible`` class decorator for this
|
|
|
|
(that's what Django uses on FileSystemStorage).
|
|
|
|
|
2020-03-06 10:52:49 +00:00
|
|
|
By default, the following methods raise ``NotImplementedError`` and will
|
2014-11-03 09:46:38 +00:00
|
|
|
typically have to be overridden:
|
2008-09-03 20:27:54 +00:00
|
|
|
|
2011-10-14 00:12:01 +00:00
|
|
|
* :meth:`Storage.delete`
|
|
|
|
* :meth:`Storage.exists`
|
|
|
|
* :meth:`Storage.listdir`
|
|
|
|
* :meth:`Storage.size`
|
|
|
|
* :meth:`Storage.url`
|
2008-09-03 20:27:54 +00:00
|
|
|
|
2014-10-15 07:42:06 +00:00
|
|
|
Note however that not all these methods are required and may be deliberately
|
2014-11-03 09:46:38 +00:00
|
|
|
omitted. As it happens, it is possible to leave each method unimplemented and
|
|
|
|
still have a working Storage.
|
|
|
|
|
|
|
|
By way of example, if listing the contents of certain storage backends turns
|
2020-03-06 10:52:49 +00:00
|
|
|
out to be expensive, you might decide not to implement ``Storage.listdir()``.
|
2014-11-03 09:46:38 +00:00
|
|
|
|
|
|
|
Another example would be a backend that only handles writing to files. In this
|
|
|
|
case, you would not need to implement any of the above methods.
|
|
|
|
|
|
|
|
Ultimately, which of these methods are implemented is up to you. Leaving some
|
|
|
|
methods unimplemented will result in a partial (possibly broken) interface.
|
|
|
|
|
2008-09-10 15:09:53 +00:00
|
|
|
You'll also usually want to use hooks specifically designed for custom storage
|
2008-09-03 20:27:54 +00:00
|
|
|
objects. These are:
|
2008-08-23 22:25:40 +00:00
|
|
|
|
2012-11-17 15:05:34 +00:00
|
|
|
.. method:: _open(name, mode='rb')
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
|
|
**Required**.
|
|
|
|
|
|
|
|
Called by ``Storage.open()``, this is the actual mechanism the storage class
|
|
|
|
uses to open the file. This must return a ``File`` object, though in most cases,
|
|
|
|
you'll want to return some subclass here that implements logic specific to the
|
2023-08-03 19:54:15 +00:00
|
|
|
backend storage system. The :exc:`FileNotFoundError` exception should be raised
|
|
|
|
when a file doesn't exist.
|
2008-08-23 22:25:40 +00:00
|
|
|
|
2012-11-17 15:05:34 +00:00
|
|
|
.. method:: _save(name, content)
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
|
|
Called by ``Storage.save()``. The ``name`` will already have gone through
|
|
|
|
``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
|
2010-08-19 19:27:44 +00:00
|
|
|
``File`` object itself.
|
Fixed a whole bunch of small docs typos, errors, and ommissions.
Fixes #8358, #8396, #8724, #9043, #9128, #9247, #9267, #9267, #9375, #9409, #9414, #9416, #9446, #9454, #9464, #9503, #9518, #9533, #9657, #9658, #9683, #9733, #9771, #9835, #9836, #9837, #9897, #9906, #9912, #9945, #9986, #9992, #10055, #10084, #10091, #10145, #10245, #10257, #10309, #10358, #10359, #10424, #10426, #10508, #10531, #10551, #10635, #10637, #10656, #10658, #10690, #10699, #19528.
Thanks to all the respective authors of those tickets.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10371 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-04-03 18:30:54 +00:00
|
|
|
|
|
|
|
Should return the actual name of name of the file saved (usually the ``name``
|
|
|
|
passed in, but if the storage needs to change the file name return the new name
|
|
|
|
instead).
|
2008-08-23 22:25:40 +00:00
|
|
|
|
2012-11-17 15:05:34 +00:00
|
|
|
.. method:: get_valid_name(name)
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
Returns a filename suitable for use with the underlying storage system. The
|
2015-05-03 04:10:24 +00:00
|
|
|
``name`` argument passed to this method is either the original filename sent to
|
|
|
|
the server or, if ``upload_to`` is a callable, the filename returned by that
|
|
|
|
method after any path information is removed. Override this to customize how
|
|
|
|
non-standard characters are converted to safe filenames.
|
|
|
|
|
2008-08-23 22:25:40 +00:00
|
|
|
The code provided on ``Storage`` retains only alpha-numeric characters, periods
|
|
|
|
and underscores from the original filename, removing everything else.
|
|
|
|
|
2019-08-28 16:17:07 +00:00
|
|
|
.. method:: get_alternative_name(file_root, file_ext)
|
|
|
|
|
|
|
|
Returns an alternative filename based on the ``file_root`` and ``file_ext``
|
|
|
|
parameters. By default, an underscore plus a random 7 character alphanumeric
|
|
|
|
string is appended to the filename before the extension.
|
|
|
|
|
2014-10-15 07:42:06 +00:00
|
|
|
.. method:: get_available_name(name, max_length=None)
|
2008-08-23 22:25:40 +00:00
|
|
|
|
|
|
|
Returns a filename that is available in the storage mechanism, possibly taking
|
|
|
|
the provided filename into account. The ``name`` argument passed to this method
|
|
|
|
will have already cleaned to a filename valid for the storage system, according
|
|
|
|
to the ``get_valid_name()`` method described above.
|
|
|
|
|
2014-10-15 07:42:06 +00:00
|
|
|
The length of the filename will not exceed ``max_length``, if provided. If a
|
|
|
|
free unique filename cannot be found, a :exc:`SuspiciousFileOperation
|
|
|
|
<django.core.exceptions.SuspiciousOperation>` exception is raised.
|
|
|
|
|
2019-08-28 16:17:07 +00:00
|
|
|
If a file with ``name`` already exists, ``get_alternative_name()`` is called to
|
|
|
|
obtain an alternative name.
|
2023-01-11 09:48:57 +00:00
|
|
|
|
|
|
|
.. _using-custom-storage-engine:
|
|
|
|
|
|
|
|
Use your custom storage engine
|
|
|
|
==============================
|
|
|
|
|
|
|
|
.. versionadded:: 4.2
|
|
|
|
|
|
|
|
The first step to using your custom storage with Django is to tell Django about
|
|
|
|
the file storage backend you'll be using. This is done using the
|
|
|
|
:setting:`STORAGES` setting. This setting maps storage aliases, which are a way
|
|
|
|
to refer to a specific storage throughout Django, to a dictionary of settings
|
|
|
|
for that specific storage backend. The settings in the inner dictionaries are
|
|
|
|
described fully in the :setting:`STORAGES` documentation.
|
|
|
|
|
|
|
|
Storages are then accessed by alias from from the
|
|
|
|
:data:`django.core.files.storage.storages` dictionary::
|
|
|
|
|
|
|
|
from django.core.files.storage import storages
|
2023-03-01 12:35:43 +00:00
|
|
|
|
2023-01-11 09:48:57 +00:00
|
|
|
example_storage = storages["example"]
|