Este documento describe las API de acceso a archivos de Django para archivos como los cargados por un usuario. Las API de nivel inferior son lo suficientemente generales como para que pueda usarlas para otros fines. Si desea manejar “archivos estáticos” (JS, CSS, etc.), consulte Gestión de archivos estáticos (por ejemplo, imágenes, JavaScript, CSS).

De forma predeterminada, Django almacena archivos localmente, usando el MEDIA_ROOT y MEDIA_URL ajustes. Los ejemplos siguientes asumen que está utilizando estos valores predeterminados.

Sin embargo, Django proporciona formas de escribir sistemas de almacenamiento de archivos personalizados que le permiten personalizar completamente dónde y cómo almacena Django los archivos. La segunda mitad de este documento describe cómo funcionan estos sistemas de almacenamiento.

Usar archivos en modelos

Cuando usas un FileField o ImageField, Django proporciona un conjunto de API que puede usar para manejar ese archivo.

Considere el siguiente modelo, utilizando un ImageField para almacenar una foto:

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

Alguna Car instancia tendrá un photo atributo que puede utilizar para obtener los detalles de la foto adjunta:

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

Este objeto – car.photo en el ejemplo – es un File objeto, lo que significa que tiene todos los métodos y atributos que se describen a continuación.

Nota

El archivo se guarda como parte de guardar el modelo en la base de datos, por lo que no se puede confiar en el nombre de archivo real utilizado en el disco hasta que se haya guardado el modelo.

Por ejemplo, puede cambiar el nombre del archivo configurando el name a una ruta relativa a la ubicación del almacenamiento de archivos (MEDIA_ROOT si está usando el predeterminado 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

Nota

Tiempo ImageField atributos de datos que no son de imagen, como height, width, y size están disponibles en la instancia, los datos de la imagen subyacente no se pueden utilizar sin volver a abrir la imagen. Por ejemplo:

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

los File objeto

Internamente, Django usa un django.core.files.File instancia en cualquier momento que necesite representar un archivo.

La mayor parte del tiempo usará un File que te ha dado Django (es decir, un archivo adjunto a un modelo como el anterior, o quizás un archivo cargado).

Si necesita construir un File usted mismo, la forma más fácil es crear uno usando un Python incorporado file objeto:

>>> from django.core.files import File

# Create a Python file object using open()
>>> f = open('/path/to/hello.world', 'w')
>>> myfile = File(f)

Ahora puede utilizar cualquiera de los atributos y métodos documentados del File clase.

Tenga en cuenta que los archivos creados de esta manera no se cierran automáticamente. Se puede utilizar el siguiente enfoque para cerrar archivos automáticamente:

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

Cerrar archivos es especialmente importante cuando se accede a campos de archivo en un bucle sobre una gran cantidad de objetos. Si los archivos no se cierran manualmente después de acceder a ellos, puede surgir el riesgo de quedarse sin descriptores de archivo. Esto puede provocar el siguiente error:

OSError: [Errno 24] Too many open files

Almacenamiento de archivos

Detrás de escena, Django delega decisiones sobre cómo y dónde almacenar archivos en un sistema de almacenamiento de archivos. Este es el objeto que realmente entiende cosas como sistemas de archivos, abrir y leer archivos, etc.

El almacenamiento de archivos predeterminado de Django viene dado por DEFAULT_FILE_STORAGE configuración; Si no proporciona explícitamente un sistema de almacenamiento, este es el que se utilizará.

Consulte a continuación los detalles del sistema de almacenamiento de archivos predeterminado integrado y consulte Escribir un sistema de almacenamiento personalizado para obtener información sobre cómo escribir su propio sistema de almacenamiento de archivos.

Objetos de almacenamiento

Aunque la mayor parte del tiempo querrá utilizar un File objeto (que delega al almacenamiento adecuado para ese archivo), puede usar los sistemas de almacenamiento de archivos directamente. Puede crear una instancia de alguna clase de almacenamiento de archivos personalizada o, a menudo más útil, puede utilizar el sistema de almacenamiento predeterminado global:

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

Ver API de almacenamiento de archivos para la API de almacenamiento de archivos.

La clase de almacenamiento del sistema de archivos incorporado

Django se envía con un django.core.files.storage.FileSystemStorage clase que implementa el almacenamiento de archivos del sistema de archivos local básico.

Por ejemplo, el siguiente código almacenará los archivos cargados en /media/photos independientemente de lo que tu MEDIA_ROOT el ajuste es:

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)

Sistemas de almacenamiento personalizados funcionan de la misma manera: puede pasarlos como el storage argumento a un FileField.

Usando un invocable

Nuevo en Django 3.1.

Puede utilizar un invocable como storage parámetro para FileField o ImageField. Esto le permite modificar el almacenamiento usado en tiempo de ejecución, seleccionando diferentes almacenamientos para diferentes entornos, por ejemplo.

Su invocable se evaluará cuando se carguen las clases de sus modelos y debe devolver una instancia de Storage.

Por ejemplo:

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)