En esta página:
Demo Github
En este Capítulo Nro 4 el cual es el último de este tutorial, vamos a continuar con la anterior parte Como crear un CRUD con Django 2 y Bootstrap 4 – Parte 3 (Python 3.7) en donde crearemos las vistas HTML para el usuario final, así mismo agregaremos mensajes que serán mostrados cada vez que el usuario realice una operación CRUD, entre otras tareas, vamos con esta 4ta y última parte del tutorial.
Bien para mostrar los postres o registros de la Base de Datos vamos a usar una vista principal en el Administrador, esta vista va tener una tabla HTML de Bootstrap 4 con las columnas Nombre, Precio, Stock, Imagen y Acciones.
En la columna Acciones irán 3 botones que son Ver, Editar y Eliminar para gestionar cada registro o postre independientemente.
Recuerda que en la tabla HTML de Bootstrap 4 vamos a listar o leer todos los datos de nuestra tabla postres y dentro de la columna Acciones tenemos el botón Ver que nos servirá para leer o mostrar los detalles de un registro o postre independientemente.
En la parte 3 de este tutorial creamos 4 archivos HTML dentro de nuestra carpeta templates que son actualizar.html, crear.html, detalles.html e index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/miapp ├── /env ├── /Include ├── /Lib ├── /Scripts ├── pyvenv.cfg ├── /app ├── /app ├── __init__.py ├── settings.py ├── urls.py ├── manage.py ├── /postres ├── /templates ├── /postres ├── actualizar.html // Creamos este archivo ├── crear.html // Creamos este archivo ├── detalles.html // Creamos este archivo ├── index.html // Creamos este archivo ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── tests.py ├── views.py |
Vistas CRUD con Bootstrap 4
Antes de crear las vistas HTML debemos de instanciar la librería o core de Bootstrap 4 junto a su archivo de estilos CSS, esto debemos hacerlo en cada archivo HTML de nuestro Sistema CRUD, lo colocamos entre las etiquetas <head></head>
1 2 3 4 5 6 7 8 9 10 11 |
<head> {# Cargamos la librería #} {% load bootstrap4 %} {# CSS Bootstrap #} {% bootstrap_css %} </head> |
Y al final de nuestro documento HTML antes de la etiqueta de cierre </body> instanciamos la librería jQuery y el archivo JS de Bootstrap 4
1 2 3 4 5 6 7 |
{# JS y jQuery Bootstrap #} {% bootstrap_javascript jquery='full' %} </body> </html> |
También definimos la configuración de la carpeta STATIC_URL en nuestro archivo settings.py
1 2 3 4 |
# Esta configuración se encuentra dentro del archivo settings.py STATIC_URL = '/static/' |
Mediante STATIC_URL le decimos a Django que usaremos la carpeta /static/ para almacenar nuestros archivos CSS, JS y las imágenes de cada registro o postre que subamos a nuestra Base de Datos.
Y en nuestro archivo HTML colocamos entre las etiquetas <head></head> la configuración de STATIC_ROOT, lo puedes colocar debajo de la llamada que hicimos al core y archivo CSS de Bootstrap 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<head> {# Cargamos la librería #} {% load bootstrap4 %} {# CSS Bootstrap #} {% bootstrap_css %} </head> {# Archivos #} {% load static %} <!-- STATIC_URL --> </head> |
Listar Postres (Home)
Vamos a empezar listando los postres en una tabla HTML con Bootstrap 4, abre el archivo index.html y agrega lo siguiente
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<table class="table table-striped table-hover"> <thead> <tr> <th width="35%">Nombre</th> <th>Precio</th> <th>Stock</th> <th>Imagen</th> <th>Acciones</th> </tr> </thead> <tbody> <!-- Recorremos los objetos o registros que tenemos en nuestra tabla 'postres' y los listamos --> {% for postre in object_list %} <tr> <td>{{ postre.nombre }}</td> <td>{{ postre.precio }}</td> <td>{{ postre.stock }}</td> <td><img src="{% static 'uploads/'%}{{postre.img}}" alt="{{postre.nombre}}" class="img-fluid" width="7%"></td> <td> <!-- Usaremos un formulario que realizará la tarea de eliminar un registro o postre desde la misma tabla HTML --> <form method="POST" action="eliminar/{{postre.id}}"> {% csrf_token %} <div class="btn-group"> <!-- Creamos 3 botones que son ver, Editar y Eliminar, nos sirven para gestionar nuestros registros o postres --> <a href="detalle/{{postre.id}}" title="Ver" type="button" class="btn btn-success">Ver </a> <a href="editar/{{postre.id}}" title="Editar" type="button" class="btn btn-primary">Editar </a> <button class="btn btn-danger" onclick="return eliminar();" type="submit"> Eliminar </button> </div> </form> </td> </tr> {% endfor %} </tbody> </table> |
También añadimos un botón Crear para ingresar nuevos registro a nuestra Base de Datos
1 2 3 4 5 |
<div align="left" class="btn_crear mb-3"> <a href="crear" type="button" class="btn btn-primary">Crear</a> </div> |
Bien con esto obtenemos nuestra vista principal (index.html) con el listado respectivo de los postres o registros.
Cada ves que en la tabla HTML aparece un registro o postre nuevo, el sistema le asigna una tira de botones que son Ver, Editar y Eliminar
Crear
Para la vista HTML de creación de un nuevo registro o postre, abre el archivo crear.html que te pedimos crearlo en la parte 3 de este tutorial, este archivo se encuentra dentro de la carpeta templates y agrégale el siguiente formulario
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<form method="post" enctype="multipart/form-data"> # Pasamos el 'csrf_token' de seguridad para poder crear un nuevo registro {% csrf_token %} <!-- {{ form.as_p }} --> <div class="form-group"> <label for="nombre" class="txt_negrita">Nombre</label> {{ form.nombre|add_class:"form-control" }} <!-- Usamos la librería 'widget_tweaks' para crear esta caja de texto --> </div> <div class="form-group"> <label for="precio" class="txt_negrita">Precio</label> {{ form.precio|add_class:"form-control" }} <!-- Usamos la librería 'widget_tweaks' para crear esta caja de texto --> </div> <div class="form-group"> <label for="stock" class="txt_negrita">Stock</label> {{ form.stock|add_class:"form-control" }} <!-- Usamos la librería 'widget_tweaks' para crear esta caja de texto --> </div> <div class="form-group"> <label for="img" class="txt_negrita">Imagen</label> {{ form.img|add_class:"form-control mb-3" }} <!-- Usamos la librería 'widget_tweaks' para crear esta caja de texto --> </div> <button type="submit" class="btn btn-primary">Aceptar</button> <a href="./" type="submit" class="btn btn-primary">Cancelar</a> </form> |
En el código del archivo crear.html puedes ver que estamos usando la librería widget_tweaks que instalamos en el capítulo 3 de este tutorial, esta librería nos permite gestionar nuestros formularios creados mediante Vistas Genéricas de Django.
Con esto tenemos nuestra vista crear.html con el formulario para ingresar un nuevo postre o registro
Detalles (Leer)
En esta vista vamos a mostrar los detalles de un archivo independientemente cada ves que el usuario haga clic en el botón Ver que se encuentra en la columna Acciones al lado de un determinado registro en la tabla HTML del archivo index.html
Agregamos el siguiente código HTML al archivo detalles.html que se encuentra en la carpeta templates, con este código imprimimos los objetos o datos con la información de un registro específico
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<h4>Detalles</h4> <p><span class="txt_negrita">Nombre:</span> <br> {{object.nombre}}</p> <p><span class="txt_negrita">Precio:</span> <br> {{object.precio}}</p> <p><span class="txt_negrita">Stock:</span> <br> {{object.stock}}</p> <p><span class="txt_negrita">Imagen:</span> <br> <img src="{% static 'uploads/'%}{{object.img}}" alt="{{object.nombre}}" class="img-fluid"> </p> <p><span class="txt_negrita">Creado:</span> <br> {{object.created_at}}</p> <p><span class="txt_negrita">Actualizado:</span> <br> {{object.updated_at}}</p> <!-- Botón para volver a la vista principal (Home) --> <a href="../" type="submit" class="btn btn-primary">Volver</a> |
Django envía el id del registro al archivo o template llamado detalles.html para mostrar los detalles de dicho registro, el envío de este id lo hace por la ruta postres/detalle/<int:pk>
1 2 3 |
path('postres/detalle/<int:pk>', PostreDetalle.as_view(template_name = "postres/detalles.html"), name='detalles'), |
Esta ruta la definimos anteriormente en la parte 3 de este tutorial, específicamente dentro del archivo urls.py
Con este tenemos nuestra vista Detalles con los datos de un registro determinado
Actualizar
Dentro de esta vista colocamos un formulario HTML para poder editar un registro determinado, dentro de cada elemento Django coloca los valores específicos de un registro o postre.
Abre el archivo actualizar.html que se encuentra en la carpeta templates y agrega el siguiente código HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<form method="post" enctype="multipart/form-data"> {% csrf_token %} <!-- {{ form.as_p }} --> <div class="form-group"> <label for="nombre" class="txt_negrita">Nombre</label> {{ form.nombre|add_class:"form-control" }} <!-- Usamos la librería 'widget_tweaks' para crear esta caja de texto --> </div> <div class="form-group"> <label for="precio" class="txt_negrita">Precio</label> {{ form.precio|add_class:"form-control" }} </div> <div class="form-group"> <label for="stock" class="txt_negrita">Stock</label> {{ form.stock|add_class:"form-control" }} </div> <div class="form-group"> <label for="img" class="txt_negrita">Imagen</label> {{ form.img|add_class:"form-control mb-3" }} <p class="txt_negrita">Imagen Actual:</p> <img src="{% static 'uploads/'%}{{object.img}}" class="img-fluid" alt="{{object.nombre}}"> </div> <button type="submit" class="btn btn-primary">Aceptar</button> <a href="../" type="submit" class="btn btn-primary">Volver</a> </form> |
Pasamos por la siguiente ruta el id del registro que vamos a Editar
1 2 3 |
path('postres/editar/<int:pk>', PostreActualizar.as_view(template_name = "postres/actualizar.html"), name='actualizar'), |
Con esto Django nos envía al archivo actualizar.html los datos de un determinado registro y los coloca dentro del formulario listos para poder ser editados
Eliminar
Para esta vista vamos a usar el archivo index.html que se encuentra dentro de la carpeta templates, en este archivo estamos listando todos los registros o postres de la Base de Datos.
En la columna Acciones puedes ver en el código que he colocado un formulario, este formulario solo nos va servir para ejecutar la eliminación de un registro desde la misma tabla HTML donde listamos los registros
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<table class="table table-striped table-hover"> <thead> <tr> <th width="35%">Nombre</th> <th>Precio</th> <th>Stock</th> <th>Imagen</th> <th>Acciones</th> </tr> </thead> <tbody> {% for postre in object_list %} <tr> <td>{{ postre.nombre }}</td> <td>{{ postre.precio }}</td> <td>{{ postre.stock }}</td> <td><img src="{% static 'uploads/'%}{{postre.img}}" alt="{{postre.nombre}}" class="img-fluid" width="7%"></td> <td> <!-- Usaremos un formulario que realizará la tarea de eliminar un registro o postre desde la misma tabla HTML --> <form method="POST" action="eliminar/{{postre.id}}"> {% csrf_token %} <div class="btn-group"> <a href="detalle/{{postre.id}}" title="Ver" type="button" class="btn btn-success">Ver </a> <a href="editar/{{postre.id}}" title="Editar" type="button" class="btn btn-primary">Editar </a> <!-- Este botón ejecuta el formulario para eliminar un registro o postre en la Base de datos --> <button class="btn btn-danger" onclick="return eliminar();" type="submit"> Eliminar </button> </div> </form> </td> </tr> {% endfor %} </tbody> </table> |
La idea es hacer la eliminación de los registros desde la misma página, no sería muy estético eliminar el registro en una nueva página HTML, salvo que tu proyecto lo requiera.
Por seguridad antes de eliminar un registro, vamos a consultar al usuario si desea eliminar un registro, dentro de nuestro botón para enviar el formulario llamamos a la función Javascript eliminar();
1 2 3 4 5 |
<button class="btn btn-danger" onclick="return eliminar();" type="submit"> Eliminar </button> |
Es decir que cuando el usuario hace clic en el botón lanzaremos una alerta con el mensaje Eliminar Producto ?
La función eliminar(); la creamos con Javascript y la colocamos al final antes de cerrar la etiqueta </body> de nuestro archivo HTML llamado index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<script type="text/javascript"> function eliminar() { var x = confirm("Eliminar Producto ?"); if (x) return true; else return false; } </script> </body> </html> |
Entonces cuando el usuario haga clic en el botón Eliminar de alguno de los registros que se encuentran en la columna Acciones de la tabla HTML, le lanzamos la alerta para que confirme la eliminación del registro
De esta manera impedimos que el usuario borre por error alguno de sus registros.
Mensajes
Dentro de nuestro archivo index.html van a recaer todos los mensajes de las operaciones Crear, Eliminar y Actualizar, es decir después de Insertar, Eliminar o Actualizar un registro o postre de la Base de Datos, mostramos un mensaje para confirmar que dicha operación ha sido realizada Correctamente.
Abre el archivo index.html que se encuentra en la carpeta templates y agrega el siguiente código
1 2 3 4 5 6 7 8 9 |
{% if messages %} <ul class="messages list-group mb-3"> {% for message in messages %} <li{% if message.tags %} class="{{ message.tags }} list-group-item list-group-item-primary"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} |
Cuando el usuario por ejemplo Edite un registro o postre, se le va mostrar un mensaje diciendo que la operación ha sido realizada correctamente, este mensaje también le va aparecer cuando Crea o Eimina un registro
La carpeta uploads
Debemos de crear una carpeta para las imágenes de cada Registro que el usuario crea, yo le pondré de nombre uploads a esta carpeta y la creamos dentro de la carpeta postres > static > uploads
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/miapp ├── /env ├── /Include ├── /Lib ├── /Scripts ├── pyvenv.cfg ├── /app ├── /app ├── __init__.py ├── settings.py ├── urls.py ├── manage.py ├── /postres ├── /templates ├── /static ├── /css ├── /uploads # Crea esta carpeta |
Bien con eso ya tenemos finalizado nuestro sistema CRUD.
Configuraciones Adicionales
Te recomendamos Por favor revisar el archivo settings.py alojado en el Repositorio GitHub de este proyecto en donde esta toda la configuración que he realizado, destacar las siguientes configuraciones
1 2 3 4 5 6 7 8 9 10 11 |
# La URL para los archivos Estáticos (CSS, JS, Imágenes, etc.) STATIC_URL = '/static/' # Las rutas para las imágenes de cada registro o postre MEDIA_URL = '/postres/' MEDIA_ROOT = os.path.join(BASE_DIR, 'postres/static/uploads') # Activamos 'CookieStorage' que nos permite enviar los mensajes de respuesta al Crear, Eliminar y Actualizar un registro MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' |
Notas
- Los pasos mencionados en este tutorial pueden cambiar en un futuro, esto no depende de nosotros si no de las empresas que dan soporte a Django, Python y MySQL que suelen cambiar el orden y las opciones de sus tecnologías.
- No te preocupes si tienes dudas con el código del Proyecto, al inicio de esta parte 4 estoy colocando el repositorio GitHub con una Demo para que puedas ver el CRUD en acción.
- Dentro del repositorio GitHub también se encuentra el archivo postres.sql que contiene los datos de la tabla postres, no olvides primero crear una Base de datos y luego importas este archivo a tu Base de datos que has creado.
Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.