Этот документ описывает API Django для работы с файлами, которые были загружены пользователем. API более низкого уровня довольно стандартны и вы можете использовать их для других целей. Если вам надо обрабатывать “статические файлы” (JS, CSS и так далее), обратитесь к Работа со статическими файлами (например изображения, JavaScript, CSS).
Как правило, Django хранит файлы локально, используя настройки MEDIA_ROOT и MEDIA_URL. Примеры, данные ниже, предполагают использование значений по умолчанию.
Однако, Django предоставляет возможность записи в пользовательские системы хранения файлов, которые позволяют полностью настроить то, как и где Django будет располагать файлы. Вторая часть этого руководства призвана описать как это работает.
Когда вы используете классы FileField или ImageField, Django предоставляет интерфейс программирования приложений (API), чтобы открыть вам доступ к файлам.
Рассмотрим следующую модель, используя ImageField для хранения фотографии:
from django.db import models
class Car(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=5, decimal_places=2)
photo = models.ImageField(upload_to='cars')
Любой экземпляр класса Car будет иметь атрибут photo, к которому можно обращаться, чтобы получить сведения о загруженной фотографии:
>>> car = Car.objects.get(name="57 Chevy")
>>> car.photo
<ImageFieldFile: chevy.jpg>
>>> car.photo.name
'cars/chevy.jpg'
>>> car.photo.path
'/media/cars/chevy.jpg'
>>> car.photo.url
'http://media.example.com/cars/chevy.jpg'
Этот объект – car.photo является файловым объектом, а значит имеет ряд атрибутов, описанных ниже.
Примечание
Файл сохраняется в базе данных как часть модели, поэтому фактическое название файла не может быть использовано до того момента, пока не будет сохранена модель, включающая его.
Например, вы можете изменить название файла, указав в атрибуте name относительный путь для хранилища файлов (MEDIA_ROOT, если вы используете по умолчанию FileSystemStorage):
>>> import os
>>> from django.conf import settings
>>> initial_path = car.photo.path
>>> car.photo.name = 'cars/chevy_ii.jpg'
>>> new_path = settings.MEDIA_ROOT + car.photo.name
>>> # Move the file on the filesystem
>>> os.rename(initial_path, new_path)
>>> car.save()
>>> car.photo.path
'/media/cars/chevy_ii.jpg'
>>> car.photo.path == new_path
True
Django использует класс django.core.files.File, который должен представлять собой объект файла. Этот объект – тонкая оболочка над встроенным файловым объектом языка Python с некоторыми дополнениями самого Django.
Большую часть времени вы будете просто использовать файловый объект, предоставляемый Django (то есть прикреплённый к соответствующей модели как указано выше или загруженный файл).
Но если вам вдруг понадобится создать объект File самостоятельно, проще всего использовать для этого указанный выше встроенный файловый объект языка Python:
>>> from django.core.files import File
# Create a Python file object using open()
>>> f = open('/tmp/hello.world', 'w')
>>> myfile = File(f)
Теперь у вас есть возможность использовать любой из атрибутов и методов стандартного класса File.
Отдавайте себе отчёт в том, что файлы, созданные таким образом, не будут автоматически закрыты. Для решения этой проблемы может быть использован следующий подход:
>>> from django.core.files import File
# Create a Python file object using open() and the with statement
>>> with open('/tmp/hello.world', 'w') as f:
... myfile = File(f)
... myfile.write('Hello World')
...
>>> myfile.closed
True
>>> f.closed
True
Закрытие файлов особенно важно при получении доступа к файлу в цикле с большим количеством объектов. Если файлы не будут закрыты вручную после получения доступа к ним, может возникнуть риск того, что все файловые дескрипторы будут исчерпаны. В свою очередь это может привести к следующей ошибке:
IOError: [Errno 24] Too many open files
За кулисами Django принимает решение о том, как и где будут сохранены ваши файлы. Фактически это означает, что Django понимает такие вещи, как файловая система, открытие и запись файлов и прочее.
Выбор места для хранения файлов задаётся в настройках DEFAULT_FILE_STORAGE. Если вы не указали иного назначения, это первое, что будет использовано.
Для получения более подробной информации о встроенной системе хранения файлов смотрите нижеследующие абзацы или обратитесь к главе о создании пользовательской системы хранения файлов Writing a custom storage system, чтобы понять, как с ней работать.
Хотя большую часть времени вам, скорее всего, будет достаточно объекта File (который осуществляет надлежащее хранение файлов), вы можете обращаться к файловой системе напрямую. У вас имеется возможность создать экземпляр объекта некоторого пользовательского класса для хранения файлов или – что зачастую более полезно – использовать систему хранения, предусмотренную по умолчанию:
>>> from django.core.files.storage import default_storage
>>> from django.core.files.base import ContentFile
>>> path = default_storage.save('/path/to/file', ContentFile('new content'))
>>> path
'/path/to/file'
>>> default_storage.size(path)
11
>>> default_storage.open(path).read()
'new content'
>>> default_storage.delete(path)
>>> default_storage.exists(path)
False
См. File storage API для получения информации об API доступа к файлам Django.
Django поставляется со встроенным классом django.core.files.storage.FileSystemStorage, который реализует основное локальное файловое хранилище.
К примеру, следующий код будет хранить загруженные файлы в /media/photos, игнорируя настройки MEDIA_ROOT.
from django.db import models
from django.core.files.storage import FileSystemStorage
fs = FileSystemStorage(location='/media/photos')
class Car(models.Model):
...
photo = models.ImageField(storage=fs)
Custom storage systems работает аналогичным образом: вы можете обратиться к нему как к аргументу storage класса FileField.
Mar 31, 2016