Cómo generar un formulario web para insertar un registro en una tabla MySQL/MariaDB (sirve para cualquier otra base de datos como Oracle, PostgreSQL, SQLite, …). Un ejemplo sobre cómo crear una tabla en MySQL/MariaDB usando Django y cómo insertar registros en esta tabla desde una aplicación web desarrollada con Django.
- Requisitos para usar Django y MySQL/MariaDB.
- Crear proyecto y aplicación web Django.
- Configurar acceso al servidor de base de datos MySQL/MariaDB.
- Crear el modelo de datos y el modelo de formulario en aplicación web Django.
- Crear plantilla (template) en aplicación web Django.
- Agregar la vista (view) a la aplicación web Django.
- Agregar el ruteo para el acceso a las URL de la aplicación.
- Hacer persistente el modelo de datos, agregar tablas y campos en base de datos MySQL/MariaDB.
- Fichero de configuración settings.py del proyecto web Django.
- Probando la aplicación web Django que inserta una factura en una base de datos MySQL.
- Descargar proyecto y aplicación web completa de ejemplo Django.
- Posibles errores y su solución.
Requisitos para usar Django y MySQL/MariaDB
Únicamente necesitaremos disponer de Django instalado en Python. En el siguiente artículo explicamos cómo instalar Django:
Para la persistencia de datos, es decir, para almacenar los datos de nuestra aplicación web desarrollada con Django en una base de datos necesitaremos disponer de un equipo con un motor de base de datos (MySQL, MariaDB, PostgreSQL, Oracle, etc.). En los siguientes enlaces explicamos cómo instalar MySQL en varios sistemas operativos:
- Instalar MySQL 8 en Linux CentOS 7 y desintalar MySQL 5.
- Instalar MySQL Community Server 5.6.12 x64 en equipo con Windows 7 Ultimate.
Y necesitaremos usuario y contraseña de acceso a esta base de datos.
Crear proyecto y aplicación web Django
En primer lugar crearemos el proyecto Django, para ello seguiremos los pasos que indicamos en este artículo:
En nuestro caso crearemos el proyecto con el nombre «proyectoa_web» y la aplicación con el nombre «proyectoa_formulario». Ejecutaremos para ello los siguientes comandos:
django-admin startproject proyectoa_web
cd proyectoa_web
python manage.py startapp proyectoa_formulario
Configurar acceso al servidor de base de datos MySQL/MariaDB
Una vez creado el proyecto y la aplicación Django, configuraremos el acceso al servidor de base de datos que queramos usar para la persistencia. Para ello editaremos el fichero settings.py ubicado en la carpeta del proyecto:
En DATABASES agregaremos los parámetros para el acceso al servidor de base de datos, los siguientes «parámetros»:
- ENGINE: para conexión con servidor MySQL/MariaDB introduciremos «django.db.backends.mysql».
- NAME: nombre del catálogo/esquema/base de datos, por ejemplo «facturas».
- USER: nombre de usuario con acceso al servidor de base de datos y con permisos suficientes para crear tablas.
- PASSWORD: contraseña del usuario anterior.
- HOST: nombre del equipo o IP del servidor de la base de datos.
- PORT: puerto de conexión al servidor de base de datos.
Quedando:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'facturas', 'USER': 'usuario_pa', 'PASSWORD': 'contraseña', 'HOST': '192.168.1.5', 'PORT': '3306', 'OPTIONS': { 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" } } } |
Para el correcto funcionamiento de la aplicación web Django, necesitaremos disponer de una base de datos (catálogo, esquema) creado previamente. En nuestro caso crearemos el catálogo «facturas» en el servidor de MySQL. Para ello podremos usar cualquier cliente de MySQL o desde la línea de comandos ejecutando:
CREATE SCHEMA ‘facturas’;
Crear el modelo de datos y el modelo de formulario en aplicación web Django
Crearemos el modelo de datos en nuestra aplicación Django, para ello editaremos el fichero models.py ubicado en la carpeta de la aplicación web, en nuestro caso en /proyectoa_formulario, y agregaremos el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 |
from django.db import models from datetime import datetime # Create your models here. class FormFactura(models.Model): numero = models.CharField(max_length=30, null=False, unique=True, verbose_name="Número") importe = models.DecimalField(max_digits=10, decimal_places=2, null=False, verbose_name="Importe") fecha = models.DateTimeField(default=datetime.now, null=True, blank=True, verbose_name="Fecha") cliente = models.CharField(max_length=200, null=False, verbose_name="Cliente") observacion = models.TextField(null=True, blank=True, verbose_name="Observación") |
Lo que hemos hecho ha sido crear una clase llamada FormFactura, de tipo models.Model (modelo de datos), que es un modelo (Model) de datos con los siguientes campos y atributos:
- numero: de tipo CharField, de tamaño máximo 30, no puede ser nulo, debe ser único y su etiqueta será «Número».
- importe: de tipo DecimalField, con 10 dígitos como máximo, de los cuales 2 serán decimales, no puede ser nulo y su etiqueta será «Importe».
- fecha: de tipo DateTimeField, con el valor por defecto la fecha actual del sistema, puede ser nulo y con su etiqueta «Fecha».
- observacion: de tipo TextField, puede ser nulo, con la etiqueta «Observación».
Todas las clases de tipo models.Model que se definan en el fichero models.py corresponderán con una tabla de la base de datos. Cuando hagamos la migración posteriormente, cada clase será una tabla. Dicha tabla contendrá los campos indicados anteriormente, con sus atributos (tipo de datos, tamaño máximo, nulo, único, …).
Por ello es recomendable tener muy claro el modelo de datos de la aplicación antes de hacer la migración. Si bien hay comandos Python y Django para sincronizar los cambios que se hagan en el modelo de datos models.py en la base de datos MySQL/MariaDB.
A continuación crearemos el modelo de formulario, basándonos en el modelo de datos anterior. Para ello editaremos el fichero forms.py de la carpeta de la aplicación y agregaremos el siguiente código:
1 2 3 4 5 6 7 |
from django import forms from .models import FormFactura class FormFacturaForm(forms.ModelForm): class Meta: model = FormFactura fields = ["numero", "importe", "fecha", "cliente", "observacion"] |
Lo que hemos hecho para forms.py ha sido agregar una clase llamada FormFacturaForm, de tipo forms.ModelForm (modelo de formulario), para establecer los campos que se mostrarán en el formulario FormFactura cuando sea instanciado. En nuestro caso mostraremos todos los campos del modelo: numero, importe, fecha, cliente y observacion. Hemos agregado un import del modelo creado anteriormente FormFactura.
Cuando se van a cargar todos los campos en el modelo de formulario se podría haber usado el siguiente código, más simple:
1 2 3 4 5 6 7 |
from django import forms from .models import FormFactura class FormFacturaForm(forms.ModelForm): class Meta: model = FormFactura fields = '__all__' |
Crear plantilla (template) en aplicación web Django
El siguiente paso será crear la plantilla (template). Como casi todo en Django tendremos infinidad de posibilidades. La más rápida es usar campos especiales para las plantillas. Crearemos un fichero llamado factura.html en la carpeta /proyectoa_formulario/templates, si no existe esta carpeta la crearemos:
Y agregaremos el siguiente contenido al fichero factura.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 30 31 32 33 34 35 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Formulario de inserción de facturas en MySQL con Django por ProyectoA</title> </head> <body> <div class="container"> <h2>Añadir factura - Proyecto A</h2> {% if messages %} <ul class="messages"> {% for message in messages %} <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} {% block content %} <div class="row"> <form action="" method="post"> {% csrf_token %} <table> {{ form }} </table> <button type="submit" class="btn btn-primary btn-sm" value="">Añadir factura</button> </form> </div> {% endblock %} </div> </body> </html> |
Esta opción de crear una plantilla html es la más rápida y sirve para comprobar y depurar errores, nos mostrará el formulario para la introducción de datos de la factura y el botón de insertar factura, sin apenas código HTML. Mostrará también un mensaje indicando si la factura se ha insertado correctamente o no:
Pero si queremos dar un mejor diseño a nuestra plantilla, podremos usar estilos CSS e incluso la biblioteca Bootstrap (o cualquier otra). Un ejemplo de uso de Bootstrap para dar un mejor diseño a nuestro formulario de inserción de factura podría ser:
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 45 46 47 48 49 50 51 52 53 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Formulario de inserción de factura en MySQL con Django por ProyectoA</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <h2>Añadir factura - Proyecto A</h2> </div> <div class="container"> {% if messages %} <div class="row"> {% for message in messages %} <div class="alert alert-{{ message.tags }}" role="alert"> <p>{{ message }}</p> </div> {% endfor %} </div> {% endif %} <form method="POST" action=""> {% csrf_token %} <div class="form-group"> <label for="numero">Número:</label> <input type="text" class="form-control" id="numero" placeholder="Número de factura" name="numero" required> </div> <div class="form-group"> <label for="importe">Importe:</label> <input class="form-control" type="number" placeholder="" value="0.00" pattern="(\d{3})([\.])(\d{2})" step="any" id="importe" name="importe" value="" required> </div> <div class="form-group"> <label for="fecha">Fecha:</label> <input type="text" class="form-control" id="fecha" name="fecha"> </div> <div class="form-group"> <label for="cliente">Cliente:</label> <input type="text" class="form-control" id="cliente" name="cliente" required> </div> <div class="form-group"> <label for="observacion">Observación:</label> <textarea class="form-control" id="observacion" name="observacion"></textarea> </div> <button type="submit" value="Submit" class="btn btn-primary">Añadir factura</button> </form> </div> </body> </html> |
Quedando esta vista con mejor diseño:
Agregar la vista (view) a la aplicación web Django
Crearemos la vista (view) para mostrar el formulario FormFactura usando la plantilla factura.html. Para ello editaremos el fichero views.py de la carpeta de la aplicación y agregaremos el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from django.shortcuts import render from .forms import FormFacturaForm from django.contrib import messages # Create your views here. def form_factura(request): form = FormFacturaForm(request.POST or None) if form.is_valid(): form.save() messages.success(request, 'Factura insertada correctamente.') form = FormFacturaForm() else: messages.error(request, 'Error al insertar factura. Revise los datos.') context = {'form': form } return render(request, 'factura.html', context) |
En el código Python anterior hemos instanciado la clase FormFacturaForm. Con esto se mostrará el formulario y su plantilla factura.html. Comprobamos si el formulario se ha ejecutado correctamente, en ese caso mostramos el mensaje «Factura insertada correctamente.» y si ha habido errores mostramos el mensaje » Error al insertar factura. Revise los datos. «. Cuando el usuario inserte una factura, la aplicación volverá a mostrar el formulario vacío para insertar una nueva factura.
Agregar el ruteo para el acceso a las URL de la aplicación
Editaremos el fichero urls.py de la carpeta del proyecto, en nuestro caso de /proyectoa_web y agregaremos el siguiente código:
1 2 3 4 5 6 7 8 |
from django.contrib import admin from django.urls import path, include from proyectoa_formulario import urls urlpatterns = [ path('admin/', admin.site.urls), path('proyectoa_formulario/', include('proyectoa_formulario.urls')), ] |
Agregaremos el fichero urls.py en la carpte ade la aplicación, en /proyectoa_formulario:
1 2 3 4 5 6 |
from django.urls import path from . import views urlpatterns = [ path('', views.form_factura, name='form_factura'), ] |
Hacer persistente el modelo de datos, agregar tablas y campos en base de datos MySQL/MariaDB
Una vez creado el modelo de datos, si queremos que se creen las tablas y campos de las tablas en el servidor de base de datos (en nuestro caso en MySQL/MariaDB). Antes de continuar con el proceso, agregaremos el siguiente código al fichero
1 |
__init__.py |
Ubicado en la carpeta del proyecto proyectoa_web:
1 2 3 |
import pymysql pymysql.install_as_MySQLdb() |
Ejecutaremos el siguiente comando para migrar todas las app que tengamos:
python manage.py migrate
O bien este otro para migrar sólo una app especificada:
python manage.py migrate proyectoa_formulario
Teniendo en cuenta que cualquier cambio que se haya hecho en los ficheros de modelos (models) se aplicará en las tablas de la base de datos.
Si ejecutamos el comando anterior nos devolverá:
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, proyectoa_formulario, sessions
Running migrations:
Applying contenttypes.0001_initial… OK
Applying auth.0001_initial… OK
Applying admin.0001_initial… OK
Applying admin.0002_logentry_remove_auto_add… OK
Applying admin.0003_logentry_add_action_flag_choices… OK
Applying contenttypes.0002_remove_content_type_name… OK
Applying auth.0002_alter_permission_name_max_length… OK
Applying auth.0003_alter_user_email_max_length… OK
Applying auth.0004_alter_user_username_opts… OK
Applying auth.0005_alter_user_last_login_null… OK
Applying auth.0006_require_contenttypes_0002… OK
Applying auth.0007_alter_validators_add_error_messages… OK
Applying auth.0008_alter_user_username_max_length… OK
Applying auth.0009_alter_user_last_name_max_length… OK
Applying auth.0010_alter_group_name_max_length… OK
Applying auth.0011_update_proxy_permissions… OK
Applying auth.0012_alter_user_first_name_max_length… OK
Applying proyectoa_formulario.0001_initial… OK
Applying sessions.0001_initial… OK
Y si ahora accedemos al servidor de base de datos con algún cliente MySQL, veremos que se ha creado la tabla proyectoa_formulario_formfactura con todos los campos que hemos indicado en el fichero models.py:
Y no sólo esto, en nuestro caso, puesto que hemos dejado la aplicación «admin» que viene por defecto en cada proyecto que se crea, también ha creado las tablas correspondientes a esta aplicación de nuestro proyecto:
auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
También algunas tablas para la gestión interna de los proyectos (migraciones) de Django:
django_admin_log
django_content_type
django_migrations
django_session
El comando «migrate» únicamente aplicará los cambios realizados, si volvemos a ejecutarlo sin haber hecho cambios en los modelos, devolverá:
Operations to perform:
Apply all migrations: admin, auth, contenttypes, proyectoa_formulario, sessions
Running migrations:
No migrations to apply.
Fichero de configuración settings.py del proyecto web Django
Realizaremos algunas modificaciones en el fichero settings.py. Si queremos que la aplicación web muestre un formulario con la biblioteca Bootstrap para los estilos CSS y queremos que muestre los mensajes con el formato de Bootstrap, añadiremos el siguiente código al fichero settings.py del proyecto web en /proyectoa_web:
1 2 3 4 5 6 |
# Para mensajes de Django vinculados con mensajes de Bootstrap MESSAGE_TAGS = {message_constants.DEBUG: 'debug', message_constants.INFO: 'info', message_constants.SUCCESS: 'success', message_constants.WARNING: 'warning', message_constants.ERROR: 'danger',} |
Nos aseguraremos de que nuestra aplicación web proyectoa_formulario está en INSTALLED_APP del fichero settings.py:
1 2 3 4 5 6 7 8 9 |
INSTALLED_APPS = [ 'proyectoa_formulario', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] |
Probando la aplicación web Django que inserta una factura en una base de datos MySQL
Una vez realizados todos los pasos anteriores, podremos probar la aplicación web Django. Para ello, desde la línea de comandos, accediendo a la carpeta del proyecto proyectoa_web, ejecutaremos el comando:
python manage.py runserver
Si hay algún error en el código o la configuración del proyecto y la aplicación, el servidor web Django nos lo mostrará en la línea de comandos.
Si la ejecución del servidor web de Dejango es correta, abriremos una ventana del navegador y accederemos a la URL del servidor y al puerto 8000 (el de defecto para el servidor web Django si no se indica otro):
http://localhost:8000
Puesto que no hemos definido una página de inicio, nos mostrará:
Para acceder a la aplicación web, usaremos la URL:
http://localhost:8000/proyectoa_formulario
Nos mostrará el formulario de inserción de factura. Si introducimos los datos y pulsamos en «Añadir factura»:
Se añadirá en la base de datos MySQL/MariaDB:
Descargar proyecto y aplicación web de ejemplo Django
Para la descarga del proyecto y aplicación web completa de ejemplo de este artículo sigue el siguiente enlace:
Posibles errores y su solución
Si al iniciar el servidor web de Django aparece este mensaje de error:
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?
Se debe a que no tenemos el módulo de MySQL instalado en Python. Para solucionarlo ejecutaremos desde la línea de comandos:
pip install pymysql
Y editaremos el fichero __init.py__ ubicado en la carpeta del proyecto:
Y agregaremos las siguientes líneas:
1 2 3 |
import pymysql pymysql.install_as_MySQLdb() |
Si al ejecutar el servidor web de Django aparece este error:
django.db.utils.OperationalError: (1049, «Unknown database ‘facturas'»)
Se debe a que no hemos creado la base de datos de la aplicación en el servidor de base de datos. Deberemos crearla como indicamos en pasos anteriores.
Si al ejecutar el serividor web de Django aparece este aviso:
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run ‘python manage.py migrate’ to apply them.
Se debe a que ha detectado que se han hecho cambios en los modelos de las aplicaciones de nuestro proyecto Django pero no se han aplicado en el sistema de persistencia, en el servidor de base de datos. Para solucionar este error podremos ejecutar el siguiente comando, que aplicará todos los cambios de los modelos (models) de datos de nuestro proyecto en la base de datos MySQL/MariaDB (o la que estemos utilizando):
python manage.py migrate