Jak napisać klasę niestandardowego magazynu plików¶
Jeśli potrzebujesz dostarczyć niestandardowy magazyn plików - popularnym przykładem jest przechowywanie plików na zdalnym systemie – możesz zrobić to definiując niestandardową klasę magazynu. Będziesz potrzebował wykonać następujące kroki:
Twój niestandardowy magazyn musi być podklasą
django.core.files.storage.Storage
:from django.core.files.storage import Storage class MyStorage(Storage): ...
Django musi być w stanie stworzyć instancje twojego magazynu bez żadnych argumentów. To znaczy bez jakiegokolwiek ustawienia z
django.conf.settings
:from django.conf import settings from django.core.files.storage import Storage class MyStorage(Storage): def __init__(self, option=None): if not option: option = settings.CUSTOM_STORAGE_OPTIONS ...
Twój magazyn musi implementować metody
_open()
i_save()
wraz z innymi metodami odpowiednimi dla twojej klasy przechowywania. Zobacz poniżej, aby dowiedzieć się więcej o tych metodach.Dodatkowo, jeśli twoja klasa dostarcza lokalny magazyn plików musi przeciążać metodę
path()
.Your storage class must be deconstructible 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 serializable, you can use the
django.utils.deconstruct.deconstructible
class decorator for this (that’s what Django uses on FileSystemStorage).
Domyślnie, następujące metody wywołują NotImplementedError
i zazwyczaj muszą być nadpisane:
Należy jednak pamiętać, że nie wszystkie te metody są wymagane i można je celowo pominąć. Tak się składa, że możliwe jest pozostawienie każdej metody niezatwierdzonej i nadal działającej pamięci masowej.
Na przykład, jeśli zawartość listy pamięci backendu okazuje się być zbyt kosztowna, możesz zdecydować się nie implementować Storage.listdir()
.
Kolejnym przykładem może być backend, który jedynie obsługi zapisywanie do pliku. W tym przypadku, mógłbyś nie potrzebować implementować żadnej z powyższych metod.
Ostatecznie, które z tych metod są zaimplementowane zależy od Ciebie. Pozostawienie niektórych metod niezaimplementowanych może w rezultacie stworzyć częściowo (prawdopodobnie zepsuty) interfejs
Dodatkowo zazwyczaj będziesz chciał używać uchwytów zaprojektowanych specjalnie do trzymania niestandardowych obiektów pamięci. To są:
-
_open
(name, mode='rb')¶
Wymagany.
Wywoływany przez Storage.open()
, jest to aktualny mechanizm używany przez klasę do otwierania pliku. Musi on zwracać obiekt File
, choć w wielu przypadkach, będziesz chciał zwrócić jakąś podklasę implementującą specyficzną logikę dla systemu pamięci
-
_save
(name, content)¶
Called by Storage.save()
. The name
will already have gone through
get_valid_name()
and get_available_name()
, and the content
will be a
File
object itself.
Powinien zwrócić aktualną nazwę pliku, który został zapisany(zazwyczaj name
jest przekazany, ale jeśli pamięć potrzebuje zmienić nazwę pliku zwróć nową nazwę).
-
get_valid_name
(name)¶
Returns a filename suitable for use with the underlying storage system. The
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.
The code provided on Storage
retains only alpha-numeric characters, periods
and underscores from the original filename, removing everything else.
-
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.
-
get_available_name
(name, max_length=None)¶
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.
The length of the filename will not exceed max_length
, if provided. If a
free unique filename cannot be found, a SuspiciousFileOperation
exception is raised.
If a file with name
already exists, get_alternative_name()
is called to
obtain an alternative name.