Subida de archivos
Subida de archivos
Documentación:
Configuración
Django usa STACIT_ROOT y STATIC_URL para servir lso archivos estáticos (css, js, assets). Para los archivos que se suben de forma dinámica:
- MEDIA_ROOT
- MEDIA_URL
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
En templates:
django.template.context_processors.media
Servidor en desarrollo
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
Test
Subir un estático a mano y comprobar que se ve en el servidor.
Subida de archivos con formularios
<form action="{% url 'upload' %}" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
Trabajar con archivos en una vista
El contenido llega en request.FILES
with open(os.path.join(settings.MEDIA_ROOT, 'archivo.txt'), 'wb+') as destination:
for chunk in request.FILES['file'].chunks():
destination.write(chunk)
Problema de seguridad
El navegador da unos valores:
upload = request.FILES['file']
size = upload.sizecontent = request.FILES['file'].read()
name = upload.name
content_type = upload.content_type
charset = upload.charset
¿Entorno de confianza?
import mimetypes
upload = request.FILES['file']
mimetype, encoding = mimetypes.guess_type(upload.name)
if mimetype is None or not mimetype.startswith('image/'):
raise ...
Ejemplo vista sencilla
from django.conf import settings
def vista_ejemplo(request):
if request.method == 'POST':
save_path = os.path.join(settings.MEDIA_ROOT, request.FILES["file_upload"].name)
with open(save_path, "wb") as output_file:
for chunk in request.FILES["file_upload"].chunks():
output_file.write(chunk)
return render(request, "media-example.html")
Uso con Django Forms
from django import forms
class UploadForm(forms.Form):
file_upload = forms.FileField()
import os
from django.conf import settings
from django.shortcuts import render
from .forms import UploadForm
def media_example(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
save_path = os.path.join(settings.MEDIA_ROOT, form.cleaned_data["file_upload"].name)
with open(save_path, "wb") as output_file:
for chunk in form.cleaned_data["file_upload"].chunks():
output_file.write(chunk)
else:
form = UploadForm()
return render(request, "media-example.html", {"form": form})
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
Imágenes con Django Forms
Instalar Pillow
class UploadForm(forms.Form):
file_upload = forms.ImageField()
import os
from PIL import Image
from django.conf import settings
from django.shortcuts import render
from .forms import UploadForm
def media_example(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
save_path = os.path.join(settings.MEDIA_ROOT, form.cleaned_data["file_upload"].name)
image = Image.open(form.cleaned_data["file_upload"])
image.thumbnail((50, 50))
image.save(save_path)
else:
form = UploadForm()
return render(request, "media-example.html", {"form": form})
Uso de Modelos
from django.db import models
class ExampleModel(models.Model):
image_field = models.ImageField(upload_to="images/")
file_field = models.FileField(upload_to="files/")
from django.shortcuts import render
from .forms import UploadForm
from .models import ExampleModel
def media_example(request):
instance = None
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
instance = ExampleModel()
instance.image_field = form.cleaned_data["image_upload"]
instance.file_field = form.cleaned_data["file_upload"]
instance.save()
else:
form = UploadForm()
return render(request, "media-example.html", {"form": form, "instance": instance})
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% if instance %}
<img src="{{ instance.image_field.url }}">
{% endif %}
Última modificación October 21, 2022: inicio django (f6c0691)