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)