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

В этом документе описываются 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самостоятельно, самый простой способ - создать его с помощью встроенного fileобъекта Python :

>>> 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

Закрытие файлов особенно важно при доступе к полям файла в цикле по большому количеству объектов. Если файлы не закрываются вручную после доступа к ним, может возникнуть риск нехватки файловых дескрипторов. Это может привести к следующей ошибке:

OSError: [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 3.1.

Вы можете использовать вызываемый объект в качестве storage параметра для FileFieldили ImageField. Это позволяет вам изменять используемое хранилище во время выполнения, например, выбирая разные хранилища для разных сред.

Ваш вызываемый объект будет оцениваться при загрузке классов ваших моделей и должен возвращать экземпляр Storage.

Например:

from django.conf import settings
from django.db import models
from .storages import MyLocalStorage, MyRemoteStorage


def select_storage():
    return MyLocalStorage() if settings.DEBUG else MyRemoteStorage()


class MyModel(models.Model):
    my_file = models.FileField(storage=select_storage)

Copyright ©2021 All rights reserved