Este documento describe las APIs de acceso a archivos de Django para archivos como aquellos subidos por un usuario. Las API de nivel inferior son lo suficientemente generales como para que puedas utilizarlas para otros propósitos. Si deseas manejar «archivos estáticos» (JS, CSS, etc.), consulta Cómo gestionar archivos estáticos (por ejemplo, imágenes, JavaScript, CSS).
Por defecto, Django almacena archivos localmente, utilizando las configuraciones MEDIA_ROOT y MEDIA_URL. Los ejemplos a continuación asumen que estás utilizando estos valores por defecto.
Sin embargo, Django proporciona formas de crear sistemas de almacenamiento personalizados de archivos que te permiten personalizar completamente dónde y cómo Django almacena archivos. La segunda mitad de este documento describe cómo funcionan estos sistemas de almacenamiento.
Cuando utilizas un FileField o ImageField, Django proporciona una serie de APIs que puedes utilizar para tratar con ese archivo.
Considera 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")
specs = models.FileField(upload_to="specs")
Cualquier instancia de Car tendrá un atributo photo que puedes 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
'https://media.example.com/cars/chevy.jpg'
Este objeto — car.photo en el ejemplo — es un objeto de tipo File, lo que significa que dispone de todos los métodos y atributos descritos a continuación.
Nota
El archivo se almacena como parte de la guardado del modelo en la base de datos, por lo que el nombre de archivo real utilizado en disco no puede confiarse hasta después de que el modelo haya sido guardado.
Por ejemplo, puedes cambiar el nombre del archivo estableciendo la propiedad name del archivo a un camino relativo a la ubicación de almacenamiento de archivos (MEDIA_ROOT si estás utilizando el almacenamiento por defecto FileSystemStorage).
>>> import os
>>> from django.conf import settings
>>> initial_path = car.photo.path
>>> car.photo.name = "cars/chevy_ii.jpg"
>>> new_path = os.path.join(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
Guarda un archivo existente en disco a un campo de tipo FileField.
>>> from pathlib import Path
>>> from django.core.files import File
>>> path = Path("/some/external/specs.pdf")
>>> car = Car.objects.get(name="57 Chevy")
>>> with path.open(mode="rb") as f:
... car.specs = File(f, name=path.name)
... car.save()
...
Nota
Mientras que los atributos de datos no relacionados con imágenes, como height, width y size, están disponibles en la instancia, los datos de imagen subyacentes no pueden ser utilizados 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>
File¶Django utiliza internamente una instancia de django.core.files.File cualquier vez que necesita representar un archivo.
La mayoría del tiempo utilizarás un File que te ha dado Django (es decir, un archivo adjunto a un modelo como el de arriba, o quizás un archivo subido).
Si necesitas construir un Archivo tú mismo, la forma más fácil es crear uno utilizando un objeto de archivo incorporado de Python:
>>> from django.core.files import File
# Create a Python file object using open()
>>> f = open("/path/to/hello.world", "w")
>>> myfile = File(f)
Ahora puedes utilizar cualquier una de las atributos y métodos documentados de la clase File.
Ten 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 acceder a campos de archivo en un bucle sobre un gran número de objetos. Si los archivos no se cierran manualmente después de acceder a ellos, puede surgir el riesgo de agotamiento de descriptores de archivo. Esto puede dar lugar al siguiente error:
OSError: [Errno 24] Too many open files
Detrás de escena, Django delega las decisiones sobre cómo y dónde almacenar archivos a 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 por defecto de Django es 'django.core.files.storage.FileSystemStorage'`. Si no proporcionas explícitamente un sistema de almacenamiento en la clave ``default del STORAGES configuración, se utilizará este.
Consulte a continuación los detalles del almacenamiento de archivos por defecto incorporado y consulte Cómo escribir una clase de almacenamiento personalizada para obtener información sobre cómo escribir su propio sistema de almacenamiento de archivos.
Aunque la mayoría de las veces querrás utilizar un objeto Archivo (que delega en el almacenamiento apropiado para ese archivo), puedes utilizar los sistemas de almacenamiento de archivos directamente. Puedes crear una instancia de alguna clase de almacenamiento de archivos personalizado o – a menudo más útil – puedes usar el sistema de almacenamiento por defecto 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
See API de almacenamiento de archivos para la API de almacenamiento de archivos.
Django incluye una clase django.core.files.storage.FileSystemStorage que implementa el almacenamiento básico de archivos en un sistema de archivos local.
Por ejemplo, el siguiente código almacenará los archivos subidos bajo /media/photos independientemente de lo que sea su configuración 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)
Los sistemas de almacenamiento personalizados :doc:` </howto/custom-file-storage>` funcionan de la misma manera: puedes pasarlos como argumento storage a un campo FileField.
Puedes usar una función llamable como el parámetro storage para FileField o ImageField. Esto te permite modificar el almacenamiento utilizado en tiempo de ejecución, seleccionando diferentes almacenes para diferentes entornos, por ejemplo.
Tu función llamable se evaluará cuando se carguen las clases de 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)
Para establecer un almacenamiento definido en la configuración STORAGES puedes usar storages:
from django.core.files.storage import storages
def select_storage():
return storages["mystorage"]
class MyModel(models.Model):
upload = models.FileField(storage=select_storage)
Porque la función llamable se evalúa cuando se cargan las clases de modelos, si necesitas sobreescribir la configuración STORAGES en pruebas, debes utilizar una clase LazyObject en lugar de eso:
from django.core.files.storage import storages
from django.utils.functional import LazyObject
class OtherStorage(LazyObject):
def _setup(self):
self._wrapped = storages["mystorage"]
my_storage = OtherStorage()
class MyModel(models.Model):
upload = models.FileField(storage=my_storage)
La LazyObject retrasa la evaluación del almacenamiento hasta que realmente se necesita, lo que permite a override_settings() tener efecto:
@override_settings(
STORAGES={
"mystorage": {
"BACKEND": "django.core.files.storage.InMemoryStorage",
}
}
)
def test_storage():
model = MyModel()
assert isinstance(model.upload.storage, InMemoryStorage)
may 31, 2026