Управление файлами
В данном документе описываются 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: cars/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 в примере – является объектом File, что означает, что он имеет все методы и атрибуты, описанные ниже.
Примечание
Файл сохраняется при сохранении модели в базе данных, поэтому фактическое имя файла, используемое на диске, нельзя гарантировать до тех пор, пока модель не будет сохранена.
Например, вы можете изменить имя файла, установив атрибут имени файла 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
Примечание
Хотя атрибуты ImageField для не-изображений, такие как height, width, и size, доступны в экземпляре, используемые данные изображения невозможно использовать без повторного открытия изображения. Например:
>>> from PIL import Image >>> car = Car.objects.get(name='57 Chevy') >>> car.photo.width 191 >>> car.photo.height 287 >>> image = Image.open(car.photo) # Raises ValueError: seek of closed file. >>> car.photo.open() <ImageFieldFile: cars/chevy.jpg> >>> image = Image.open(car.photo) >>> image <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=191x287 at 0x7F99A94E9048>
Объект File
Внутренне Django использует экземпляр django.core.files.File всякий раз, когда ему нужно представить файл.
В большинстве случаев вы просто используете File , который предоставляет Django (например, файл, прикреплённый к модели, как показано выше, или, возможно, загруженный файл).
Если вам нужно создать File самостоятельно, самый простой способ — создать его с помощью встроенного объекта Python file:
>>> from django.core.files import File
# Create a Python file object using open()
>>> f = open('/path/to/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('/path/to/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; если вы не явно не зададите систему хранения, будет использована эта.
Подробности встроенной системы хранения файлов см. ниже, а информацию о написании собственной системы хранения файлов см. в разделе Написание пользовательской системы хранения.
Объекты хранения
Хотя в большинстве случаев вам нужно будет использовать объект File (который делегирует соответствующему хранилищу для этого файла), вы можете использовать системы хранения файлов напрямую. Вы можете создать экземпляр какого-либо пользовательского класса системы хранения файлов или, что часто более полезно, использовать глобальную систему хранения по умолчанию:
>>> from django.core.files.base import ContentFile
>>> from django.core.files.storage import default_storage
>>> path = default_storage.save('path/to/file', ContentFile(b'new content'))
>>> path
'path/to/file'
>>> default_storage.size(path)
11
>>> default_storage.open(path).read()
b'new content'
>>> default_storage.delete(path)
>>> default_storage.exists(path)
False
См. API системы хранения файлов для API системы хранения файлов.
Встроенный класс хранения файловой системы
Django поставляется с классом django.core.files.storage.FileSystemStorage, который реализует базовые локальные файловые системы.
Например, следующий код сохранит загруженные файлы в /media/photos независимо от значения вашей настройки MEDIA_ROOT:
from django.core.files.storage import FileSystemStorage
from django.db import models
fs = FileSystemStorage(location='/media/photos')
class Car(models.Model):
...
photo = models.ImageField(storage=fs)
Пользовательские системы хранения работают аналогичным образом: вы можете передать их в качестве аргумента storage для FileField.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.2/topics/files/