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

Этот документ описывает 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

Объект 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
'/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 поставляется со встроенным классом 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.