Tabla de Contenido
Crear el proyecto Django
Una vez tenemos preparado el entorno con Django instalado, abrimos la terminal y ejecutamos el comando para generar un nuevo proyecto:
1
django-admin startproject _site .
Remplaza _site
con el nombre que desees para el proyecto. Esto generar谩 la estructura de archivos y configuraciones b谩sicas para el proyecto Django.
Instalar Pillow
Primero, necesitamos instalar Pillow, que es la biblioteca que Django utiliza para manejar im谩genes. Ejecutar el siguiente comando:
1
pip install pillow
Crear una aplicaci贸n
Una vez que hayas creado el proyecto Django, podemos crear una aplicaci贸n dentro del proyecto. Abrimos la terminal en la carpeta ra铆z del proyecto. Luego, ejecuta el siguiente comando:
1
python manage.py startapp galeria
Remplaza galeria
con el nombre que quieras darle a la aplicaci贸n. Esto crear谩 una nueva carpeta con la estructura necesaria para la aplicaci贸n.
Configurar la aplicaci贸n en el proyecto
Antes de continuar, es importante configurar adecuadamente la aplicaci贸n y el proyecto Django. Abrimos el archivo settings.py
dentro de la carpeta del proyecto y realizamos las siguientes modificaciones:
INSTALLED_APP = [
...,
'galeria'
]
# En la secci贸n MEDIA_URL y MEDIA_ROOT, agregamos lo siguiente
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Estas configuraciones son necesarias para que Django pueda manejar la subida y visualizaci贸n de im谩genes.
Crear el modelo Imagen
En esta etapa, definiremos el modelo necesario para almacenar las im谩genes y sus descripciones o subt铆tulo. Abrimos el archivo models.py
de la carpeta de la aplicaci贸n y definimos el modelo:
from django.db import models
import os
class Imagen(models.Model):
caption = models.CharField(max_length=100)
image = models.ImageField(upload_to='images/%Y/%m/%d')
def delete(self, *args, **kwars):
# Guarda la ruta del archivo de imagen
imagen_path = self.image.path
# Primero, eliminamos el archivo de la imagen
super().delete(*args, **kwars)
if os.path.isfile(imagen_path):
os.remove(imagen_path)
# Eliminar carpetas vac铆as utilizando un bucle while
folder_path = os.path.dirname(imagen_path)
while folder_path:
if os.path.exists(folder_path):
try:
os.rmdir(folder_path) # intenta eliminar la carpeta
except OSError:
break # La carpeta no est谩 vac铆a, no se elimina
else:
break # Se sale del bucle si la carpeta no existe
folder_path = os.path.dirname(folder_path) # movemos hacia la carpeta padre
def __str__(self):
return self.caption
En este modelo, hemos definido el campo caption
para el texto que acompa帽ar谩 a la imagen y definimos image
para la imagen en s铆. La imagen se guardar谩 en la carpeta media/images/
siguiendo la estructura a帽o, mes y d铆a en la que se subi贸. Lo interesante aqu铆 es que sobrescribimos el m茅todo delete
para que cuando eliminemos una instancia que tenga una imagen asociada, es importante tambi茅n eliminar el archivo f铆sico del sistema de archivos para evitar ocupar espacio innecesario.
Crear el formulario de la imagen
A continuaci贸n, vamos a crear un formulario para permitir a los usuarios subir im谩genes. Crea un nuevo archivo llamado forms.py
dentro de la carpeta de la aplicaci贸n y agrega el siguiente c贸digo:
1
2
3
4
5
6
7
from django import forms
from .model import Imagen
class ImagenForm(forms.ModelForm):
class Meta:
model = Imagen
fields = ('caption', 'image')
Este formulario se vincula directamente con el model Imagen
que definimos anteriormente. Los campos caption
y image
se mostrar谩n en el formulario.
Crear las vistas de la aplicaci贸n
Ahora, debemos definir las vistas necesarias para la subida y visualizaci贸n de las im谩genes de nuestra aplicaci贸n, modificamos el archivo views.py
dentro de la carpeta de la aplicaci贸n para definir la vista que manejar谩 la subida de im谩genes:
from django.shortcuts import render, redirect, get_object_or_404
from .forms import ImagenForm
from .models import Imagen
def index(request):
if request.method == 'POST':
form = ImagenForm(request.POST, request.FILES)
if form.es_valid():
form.save()
return redirect('index')
else:
form = ImagenForm()
images = ImageField.objects.all()
return render(request, 'index.html', {'form': form, 'images': images})
def eliminar_imagen(request, id):
imagen = get_object_or_404(Imagen, id=id)
imagen.delete()
return redirect('index')
En esta vista, verificamos si el m茅todo de la solicitud es POST
. Si es as铆, creamos una instancia del formulario ImagenForm
y verificamos si es v谩lido. Si pasa esta validaci贸n, guardamos el formulario y redirigimos al usuario nuevamente a la p谩gina principal. Si la solicitud no es POST
, simplemente mostramos el formulario vac铆o.
Tambi茅n obtenemos todas las instancias de las im谩genes almacenadas en la base de datos y las pasamos al contexto del renderizado de la p谩gina.
Por 煤ltimo tenemos la vista que nos permitir谩 eliminar la instancia, y llamar谩 al m茅todo delete
que sobrescribimos anteriormente.
Configurar las URL de la aplicaci贸n
Por 煤ltimo, necesitamos definir las URLs necesarias para acceder a las vistas de nuestra aplicaci贸n. Abrimos el archivo urls.py
de la carpeta del proyecto y agregamos el siguiente c贸digo:
from django.contrib import admin
from django.urls import path
from galeria import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name='index'),
path('delete/<int:id>/', views.eliminar_imagen, name='eliminar_imagen')
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Para manejar los archivos que suben los usuarios, es necesario la configuraci贸n de MEDIA_URL
y MEDIA_ROOT
en settings.py
que ya hicimos en pasos anteriores, la variable settings.DEBUG
indica si estamos en modo desarrollo (True
) o en modo producci贸n (False
), en modo desarrollo, es com煤n servir los archivos est谩ticos y multimedia directamente desde Django, lo que es conveniente para pruebas y el desarrollo.
Al agregar urlpatterns += static(...)
, estamos a帽adiendo nuevas rutas que Django utilizar谩 para servir archivos multimedia. Para explicarlo mejor, la funci贸n static(...)
crea patrones de URL para acceder a los archivos multimedia. Toma dos argumentos:
settings.MEDIA_URL
: La URL base para acceder a los archivos multimedia. Por ejemplo, si est谩 configurado como/media/
, las im谩genes estar谩n disponible en rutas comohttp://localhost:8000/media/path/image.jpg
.document_root=settings.MEDIA_ROOT
: Es la carpeta o directorio en el sistema de archivos donde se almacenan esos archivos. Este es el path absoluto en el que Django buscar谩 los archivos que se soliciten.
Mostrar las im谩genes y el formulario
Una vez tengamos configurado correctamente la aplicaci贸n de Django, podr谩s acceder a los archivos para renderizarlos en el template. Ahora creamos la carpeta templates
como una subcarpeta de la aplicaci贸n y dentro se crea el archivo index.html
con el siguiente c贸digo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django upload images example</title>
</head>
<body>
<form method="POST" enctype="multipart/form-data"> <!-- requerido a帽adir el enctype -->
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Guardar</button>
</form>
{% for image in images %}
<figure style="display: inline-block;">
<img src="{{ image.image.url }}" alt="{{ image.caption }}" height="200" width="200">
<figcaption>{{ image.caption }}</figcaption><br />
<a href="{% url 'eliminar_imagen' image.id %}">Eliminar</a>
</figure>
{% endfor %}
</body>
</html>