Cuando Django maneja una subida de archivo, los datos del archivo terminan siendo colocados en request.FILES (para obtener más información sobre el objeto request consulte la documentación para objetos de solicitud y respuesta). Este documento explica cómo se almacenan los archivos en disco y memoria, y cómo personalizar el comportamiento por defecto.
Advertencia
Hay riesgos de seguridad si estás aceptando contenido subido desde usuarios no confiables! Consulta el tema sobre la seguridad del contenido subido por usuarios en la guía de seguridad para obtener detalles de mitigación.
Considera un formulario que contenga un campo de archivo FileField:
forms.py¶from django import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
Una vista que maneje este formulario recibirá los datos del archivo en request.FILES, que es un diccionario que contiene una clave para cada campo de archivo (o imagen) en el formulario. Por lo tanto, los datos del formulario anterior serían accesibles como request.FILES['file'].
Tenga en cuenta que request.FILES solo contendrá datos si el método de solicitud fue POST, se enviaron al menos un campo de archivo y la etiqueta <form> que envió la solicitud tiene la atributo enctype="multipart/form-data". De lo contrario, request.FILES estará vacío.
La mayoría del tiempo, pasarás los datos del archivo desde request en el formulario como se describe en Asociar archivos subidos a un formulario. Esto podría verse algo así:
views.py¶from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file
def upload_file(request):
if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES["file"])
return HttpResponseRedirect("/success/url/")
else:
form = UploadFileForm()
return render(request, "upload.html", {"form": form})
Tenga en cuenta que debemos pasar request.FILES al constructor del formulario; de esta manera, los datos del archivo se vinculan a un formulario.
Aquí hay una forma común de manejar un archivo subido:
def handle_uploaded_file(f):
with open("some/file/name.txt", "wb+") as destination:
for chunk in f.chunks():
destination.write(chunk)
Recorrer UploadedFile.chunks() en lugar de usar read() garantiza que archivos grandes no sobrecarguen la memoria del sistema.
Hay unos pocos otros métodos y atributos disponibles en objetos UploadedFile; consulte UploadedFile para una referencia completa.
Si estás guardando un archivo en un objeto Model con un campo de tipo FileField, utilizar una instancia de ModelForm hace que este proceso sea mucho más fácil. El objeto del archivo se guardará en la ubicación especificada por el argumento upload_to del campo de tipo FileField correspondiente cuando se llama a form.save():
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField
def upload_file(request):
if request.method == "POST":
form = ModelFormWithFileField(request.POST, request.FILES)
if form.is_valid():
# file is saved
form.save()
return HttpResponseRedirect("/success/url/")
else:
form = ModelFormWithFileField()
return render(request, "upload.html", {"form": form})
Si estás construyendo un objeto manualmente, puedes asignar el objeto del archivo desde request.FILES al campo de tipo file en el modelo:
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField
def upload_file(request):
if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
instance = ModelWithFileField(file_field=request.FILES["file"])
instance.save()
return HttpResponseRedirect("/success/url/")
else:
form = UploadFileForm()
return render(request, "upload.html", {"form": form})
Si estás construyendo un objeto manualmente fuera de una solicitud, puedes asignar un objeto como File a el campo de tipo FileField
from django.core.management.base import BaseCommand
from django.core.files.base import ContentFile
class MyCommand(BaseCommand):
def handle(self, *args, **options):
content_file = ContentFile(b"Hello world!", name="hello-world.txt")
instance = ModelWithFileField(file_field=content_file)
instance.save()
Si deseas subir múltiples archivos utilizando un campo de formulario único, crea una clase derivada del widget del campo y establece su atributo allow_multiple_selected en True.
Para que tales archivos sean validados todos por tu formulario (y el valor del campo incluya a todos ellos), también deberás crear una clase derivada de FileField. Consulta la sección siguiente para un ejemplo.
Campo de archivo múltiple
Django probablemente tenga una función de soporte para campos de archivo múltiples en algún momento del futuro.
forms.py¶from django import forms
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [single_file_clean(d, initial) for d in data]
else:
result = [single_file_clean(data, initial)]
return result
class FileFieldForm(forms.Form):
file_field = MultipleFileField()
Luego, sobrescribe el método form_valid() de tu clase derivada de FormView para manejar subidas de archivos múltiples:
views.py¶from django.views.generic.edit import FormView
from .forms import FileFieldForm
class FileFieldFormView(FormView):
form_class = FileFieldForm
template_name = "upload.html" # Replace with your template.
success_url = "..." # Replace with your URL or reverse().
def form_valid(self, form):
files = form.cleaned_data["file_field"]
for f in files:
... # Do something with each file.
return super().form_valid(form)
Advertencia
Estos son los textos traducidos:
Cuando un usuario carga un archivo, Django pasa los datos del archivo a un cargador de subida – una pequeña clase que maneja los datos del archivo mientras se cargan. Los cargadores de subida están definidos inicialmente en la configuración FILE_UPLOAD_HANDLERS, que tiene el valor por defecto:
[
"django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler",
]
Juntos, MemoryFileUploadHandler y TemporaryFileUploadHandler proporcionan el comportamiento predeterminado de Django para cargar archivos de subida de leyendo los pequeños en memoria y los grandes en disco.
Puedes escribir cargadores personalizados que personalicen cómo maneja Django los archivos. Podrías, por ejemplo, utilizar cargadores personalizados para imponer cuotas a nivel de usuario, comprimir datos en tiempo real, renderizar barras de progreso y enviar incluso datos a otra ubicación de almacenamiento directamente sin almacenarlos localmente. Consulta Escribiendo manejadores de carga personalizados para obtener detalles sobre cómo puedes personalizar o reemplazar completamente el comportamiento de carga.
Antes de guardar los archivos cargados, los datos necesitan ser almacenados en alguna parte.
Por defecto, si un archivo subido es menor que 2.5 megabytes, Django mantendrá la totalidad del contenido de la carga en memoria. Esto significa que guardar el archivo implica únicamente una lectura desde memoria y una escritura a disco y así es muy rápido.
Sin embargo, si un archivo subido es demasiado grande, Django escribirá el archivo subido a un archivo temporal almacenado en la carpeta de archivos temporales del sistema. En una plataforma Unix-like esto significa que puedes esperar a que Django genere un archivo llamado algo como /tmp/tmpzfp6I6.upload. Si una carga es lo suficientemente grande, puedes ver cómo este archivo crece en tamaño mientras Django transfiere los datos a disco.
Estas especificaciones – 2.5 megabytes; /tmp; etc. – son «valores por defecto razonables» que se pueden personalizar tal como se describe en la siguiente sección.
Hay unos pocos ajustes que controlan el comportamiento de la carga de archivos en Django. Consulte Configuración de carga de archivos para obtener más detalles.
A veces, las vistas particulares requieren un comportamiento de carga diferente. En estos casos, puedes sobrescribir los manipuladores de carga por solicitud modificando request.upload_handlers. Por defecto, esta lista contendrá los manipuladores de carga dados por FILE_UPLOAD_HANDLERS, pero puedes modificar la lista como cualquier otra lista.
Por ejemplo, supongamos que has escrito un ProgressBarUploadHandler que proporciona retroalimentación sobre el progreso de la carga a algún tipo de widget AJAX. Agregarías este manipulador a tus manipuladores de carga de esta manera:
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
Usando list.insert(), como se muestra arriba, garantiza que el manipulador del progreso se coloque al principio de la lista. Dado que los manipuladores de carga se ejecutan en orden, este emplazamiento garantiza que el manipulador del progreso se ejecute antes de los manipuladores predeterminados, lo que permite rastrear el progreso a lo largo de toda la carga.
Si deseas reemplazar completamente los manipuladores de carga, puedes asignar una nueva lista:
request.upload_handlers = [ProgressBarUploadHandler(request)]
Nota
Solo puedes modificar los manipuladores de carga antes acceder a request.POST o request.FILES – no tiene sentido cambiar los manipuladores de carga después de que el manejo de la carga ya ha comenzado. Si intentas modificar request.upload_handlers después de leer desde request.POST o request.FILES, Django lanzará un error.
Por lo tanto, siempre debes modificar los manipuladores de carga tan pronto como sea posible en tu vista.
Además, request.POST se accede por CsrfViewMiddleware que está habilitado por defecto. Esto significa que necesitarás usar csrf_exempt() en tu vista para permitirte cambiar los manipuladores de carga. Luego necesitarás usar csrf_protect() en la función que realmente procesa la solicitud. Tenga en cuenta que esto significa que los manipuladores pueden comenzar a recibir la carga del archivo antes de que se hayan realizado las comprobaciones CSRF. Ejemplo de código:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_exempt
def upload_file_view(request):
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
return _upload_file_view(request)
@csrf_protect
def _upload_file_view(request):
# Process request
...
Si estás utilizando una vista basada en clases, necesitarás utilizar csrf_exempt() en su método dispatch() y csrf_protect() en el método que realmente procesa la solicitud. Ejemplo de código:
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@method_decorator(csrf_exempt, name="dispatch")
class UploadFileView(View):
def setup(self, request, *args, **kwargs):
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
super().setup(request, *args, **kwargs)
@method_decorator(csrf_protect)
def post(self, request, *args, **kwargs):
# Process request
...
may 31, 2026