# Τεκμηρίωση του Django - 1.10.7

# Γράφοντας ένα δικό σας σύστημα αποθήκευσης (storage system)

Αν θέλετε να έχετε το δικό σας σύστημα αποθήκευσης αρχείων – ένα συνηθισμένο παράδειγμα είναι η αποθήκευση αρχείων σε ένα απομακρυσμένο σύστημα – μπορείτε να το κάνετε ορίζοντας μια δικιά σας κλάση αποθήκευσης (storage class). Θα χρειαστεί να ακολουθήσετε τα παρακάτω βήματα:

1. Το δικό σας σύστημα αποθήκευσης θα πρέπει να είναι μια subclass της κλάσης `django.core.files.storage.Storage`:

       from django.core.files.storage import Storage

       class MyStorage(Storage):
           ...

2. Το Django πρέπει να είναι σε θέση να αρχικοποιεί το δικό σας σύστημα αποθήκευσης χωρίς arguments. Αυτό σημαίνει ότι τυχόν ρυθμίσεις του δικού σας συστήματος θα πρέπει να λαμβάνονται από το γενικό αρχείο ρυθμίσεων `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
               ...

3. Η κλάση αποθήκευση σας πρέπει να υλοποιεί τις μεθόδους `_open()` και `_save()`, μαζί με οποιεσδήποτε άλλες, απαραίτητες για τις ανάγκες σας. Για περισσότερα σχετικά με αυτές τις μεθόδους, δείτε παρακάτω.

   Επιπροσθέτως, αν η κλάση σας παρέχει τη δυνατότητα τοπικής αποθήκευσης των αρχείων, θα πρέπει να παρακάμπτει (override) τη μέθοδο `path()`.

4. Η κλάση αποθήκευσης σας θα πρέπει να είναι deconstructible προκειμένου να γίνει serialized όταν χρησιμοποιείται πάνω σε ένα πεδίο μέσα σε κάποιο migration. Αν το πεδίο σας έχει arguments τα οποία είναι και αυτά serializable, μπορείτε να χρησιμοποιήσετε τον decorator `django.utils.deconstruct.deconstructible` (αυτό χρησιμοποιεί και το Django στο σύστημα αποθήκευσης FileSystemStorage).

Από προεπιλογή, οι ακόλουθες μέθοδοι κάνουν raise το σφάλμα NotImplementedError που σημαίνει ότι πρέπει να γίνουν overridden:

- `Storage.delete()`
- `Storage.exists()`
- `Storage.listdir()`
- `Storage.size()`
- `Storage.url()`

Υπόψιν ότι δεν είναι απαραίτητο, όλες αυτές οι μέθοδοι, να υλοποιηθούν και μερικές μπορούν σκοπίμως να παραλειφθούν. Παραβλέποντας, λοιπόν, μερικές από αυτές το σύστημα αποθήκευσης σας θα μπορεί να λειτουργεί.

Αν, για παράδειγμα η εμφάνιση των αρχείων υπό τη μορφή λίστας φαίνεται ακριβή, για το σύστημα, διαδικασία, μπορείτε να μην υλοποιήσετε τη μέθοδο Storage.listdir.

Άλλο παράδειγμα είναι ένα άλλο σύστημα αποθήκευσης που μοναδικός του ρόλος είναι η εγγραφή σε αρχεία. Σε αυτή την περίπτωση δεν χρειάζεται να υλοποιήσετε καμία από τις παραπάνω μεθόδους.

Με άλλα λόγια, το ποιες μέθοδοι θα υλοποιηθούν εξαρτάται από σας και τις ανάγκες σας. Από την άλλη, αν μερικές δεν υλοποιηθούν θα καταλήξετε με ένα λειψό (πιθανόν χαλασμένο) interface.

Επίσης, ίσως να θέλατε να χρησιμοποιήσετε κάποια hooks τα οποία έχουν σχεδιαστεί για παραμετροποιήσιμα συστήματα αποθήκευσης. Αυτά είναι:

`_open`(name, mode='rb')

Υποχρεωτικό

Η μέθοδος αυτή καλείται από την `Storage.open()`. Αυτός είναι ο ουσιαστικός μηχανισμός της κλάσης αποθήκευσης για να ανοίξει ένα αρχείο. Πρέπει να επιστρέφει ένα `File` object, αλλά στις περισσότερες περιπτώσεις, θα θέλατε να επιστρέφει κάποια subclass η οποία θα υλοποιεί τη λογική που βασίζεται πάνω στο σύστημα αποθήκευσης.

`_save`(name, content)

Η μέθοδος αυτή καλείται από την `Storage.save()`. Το όρισμα `name` θα έχει περάσει ήδη από την μέθοδο `get_valid_name()` και `get_available_name()` και το όρισμα `content` θα είναι ένα `File` object.

Θα πρέπει να επιστρέφει το όνομα του αρχείου που αποθηκεύεται (συνήθως αυτό θα είναι το `name` που περνάει ως όρισμα. Αλλά αν το σύστημα αποθήκευσης χρειαστεί να αλλάξει το όνομα του αρχείου πριν την αποθήκευση του, θα πρέπει να επιστρέψετε το νέο όνομα).

`get_valid_name`(name)

Επιστρέφει το όνομα του αρχείου το οποίο θεωρείται έγκυρο για να αποθηκευτεί στη συνέχεια από το σύστημα αποθήκευσης. Το όρισμα `name` είναι είτε το αρχικό όνομα του αρχείου που στάλθηκε στον server είτε, αν το `upload_to` είναι κάποιο callable, το όνομα που επεστράφη από αυτή τη μέθοδο αφού έχει αφαιρεθεί κάθε πληροφορία σχετικά με το path του αρχείου. Μπορείτε να παρακάμψετε αυτή τη μέθοδο για να ελέγξετε το πως οι μη-τυποποιημένοι χαρακτήρες μπορούν να μετατραπούν σε έγκυρα-ασφαλή ονόματα αρχείων.

Σε παλαιότερες εκδόσεις, αυτή η μέθοδος δεν καλούταν αν το `upload_to` ήταν callable.

Ο κώδικας του `Storage` διατηρεί μόνο τους αλφαριθμητικούς χαρακτήρες, τις τελείες και τις κάτω παύλες από τα αρχικά ονόματα των αρχείων (αυτά που επιλέγονται προς αποθήκευση), αφαιρώντας οποιονδήποτε άλλον χαρακτήρα.

`get_available_name`(name, max_length=None)

Επιστρέφει ένα όνομα αρχείου το οποίο είναι διαθέσιμο στο μηχανισμό αποθήκευσης και πιθανόν να λαμβάνει υπόψιν του το, περασμένο ως όρισμα, όνομα του αρχείου. Το όρισμα `name` θα έχει ήδη μετατραπεί σε κάποιο έγκυρο όνομα αρχείου για αποθήκευση σύμφωνα με την μέθοδο `get_valid_name()` που περιγράφηκε πιο πάνω.

Το μήκος του ονόματος του αρχείου δεν μπορεί να υπερβαίνει το `max_length`, αν αυτό δίνεται. Αν ένα μοναδικό όνομα αρχείου δεν μπορεί να βρεθεί, τότε γίνεται raise το exception `SuspiciousFileOperation`.

Αν κάποιο αρχείο με το όνομα `name` υπάρχει ήδη, τότε θα προστεθούν μετά το όνομα, ο χαρακτήρας της κάτω παύλας μαζί με 7 τυχαίους αλφαριθμητικούς χαρακτήρες πριν την κατάληξη του αρχείου.