Cargar im谩genes (archivos) - Django

← Men煤 responsive con CSS Registro de usuarios - Django →
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:

_site/settings.py
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:

galeria/models.py
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:

galeria/forms.py
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:

galeria/views.py
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:

_site/urls.py
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 como http://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:

templates/index.html
<!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>

Captura de resultado

img

Repositorio

  • github

  • 1
    
    gh repo clone EniDev911/django-carga-de-archivos
    
  • 1
    
    git clone git@github.com:EniDev911/django-carga-de-archivos.git
    
← Men煤 responsive con CSS Registro de usuarios - Django →