Управление файлами

Этот документ описывает API Django для работы с файлами, которые были загружены пользователем. API более низкого уровня довольно стандартны и вы можете использовать их для других целей. Если вам надо обрабатывать “статические файлы” (JS, CSS и так далее), обратитесь к Работа со статическими файлами (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
u'cars/chevy.jpg'
>>> car.photo.path
u'/media/cars/chevy.jpg'
>>> car.photo.url
u'http://media.example.com/cars/chevy.jpg'

Этот объект – car.photo является файловым объектом, а значит имеет ряд атрибутов, описанных ниже.

Примечание

Файл сохраняется в базе данных как часть модели, поэтому фактическое название файла не может быть использовано до того момента, пока не будет сохранена модель, включающая его.

Объект File

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, чтобы понять как с ней работать.

Объект Storage

Хотя большую часть времени вам, скорее всего, будет достаточно объекта 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
u'/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.

Встроенный класс FileSystemStorage

Django поставляется со встроенным классом FileSystemStorage (его можно импортировать из django.core.files.storage), который реализует основное локальное файловое хранилище. При его инициализации вы можете передать два аргумента:

Агрумент

Описание

location

Опционально. Указывает абсолютный путь к директории, куда будут помещены медиа файлы. Если это не указано, файлы будут располагаться в соответствии с настройками MEDIA_ROOT.

base_url

Опционально. URL-адрес, указывающий на директорию, куда будут помещены медиа файлы. Если это не указано, по умолчанию будет использоваться значение из настроек вашего MEDIA_URL.

К примеру, следующий код будет хранить загруженные файлы в /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.