Mostrando entradas con la etiqueta mysql. Mostrar todas las entradas
Mostrando entradas con la etiqueta mysql. Mostrar todas las entradas

viernes, 22 de octubre de 2021

Guía rápida para crear un servidor web casero con LAMP y WordPress en Rapsberry Pi

Imagen de worpress para la entrada


Como dice la wikipedia " Wordpress es un sistema de gestión de contenidos enfocado a la creación de cualquier tipo de página web". Y no solo eso, desde la raspberry pi, una vez creado el contenido podremos servir esa página al mundo exterior sin necesidad de contratar un alojamiento en ningún sitio.

Vamos con ello.

1) instalar el servidor web apache

Primeramente y como siempre hacemos procedemos a actualizar el sistema. 

pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get full-upgrade

Instalamos el servidor, en este caso apache.

pi@raspberrypi:~ $ sudo apt-get install apache2 -y

Vamos a necesitar conocer la IP de la rapsberry pi en nuestra red local. Si no tienes una dirección estática o no la sabes puedes conocerla con el siguiente comando:

pi@raspberrypi:~ $ hostname -I
Luego abre un navegador web y entra en http://localhost o si es desde otro equipo de la red local con la ip local de la rapsberry que obtuviste con el comando anterior (por ejemplo http://192.168.1.58) y saldrá la página de bienvenida de apache si todo ha ido bien.

página inicial del servidor apache


2) Instalar php necesario para que funcione wordpress.

> sudo apt-get install php -y

entramos en:

> cd /var/www/html/

borramos index.html 

> sudo rm index.html
y para para comprobar si funciona con un editor de texto, nano por ejemplo (sudo nano index.php), crearemos un archivo llamado index.php con el siguiente contenido.
<?php echo "hello world "; ?>
<?php echo date('Y-m-d H:i:s'); ?>
<?php phpinfo(); ?>

Guardamos el archivo y salimos del editor.

Para comprobar que funciona entramos en un navegador y tecleamos htpp://localhost, o si accedemos desde otro ordenador de nuestra red, tecleamos la dirección IP de la Raspberry.

Deberíamos ver esta pantalla.

pantalla de bienvenida de php


sino vemos el mensaje podemos probar a reiniciar el servidor web con:

> sudo service apache2 restart


3) Instalar MySQL

Instalamos MariaDb junto con los paquetes PHP_MySQL.

> sudo apt-get install mariadb-server php-mysql -y

volvemos a reiniciar el servidor:

> sudo service apache2 restart


4) Instalar wordpress

Volvemos al directorio /var/www/html/ donde tenemos index.php y una vez dentro borramos todo el contenido.

> sudo rm index.php

Descargamos la versión mas reciente de wordpress con:

sudo wget http://wordpress.org/latest.tar.gz

extraemos su contenido con:

 sudo tar xzf latest.tar.gz

Ahora hay que pasar todo el contenido de la carpeta wordpress que se habrá creado en el directorio, a la actual en la que estamos situados (/var/www/html/) con :

> sudo mv wordpress/* .

ordenamos un poco las cosas eliminando el archivo descargado y el directorio wordpress

> sudo rm -rf wordpress latest.tar.gz

Por ultimo damos permisos al usuario Apache para gestionar estos archivos.

> sudo chown -R www-data: .

Lo que sigue hasta el paso 5 es opcional:

Para gestionar la base de datos de forma más visual podemos instalar un gestor de mysql como phpmyadmin.

> sudo apt-get install phpmyadmin

Durante la instalación nos preguntará en que servidor queremos instalarlo

seleccion de apache en la instalación de phpmyadmin

, seleccionaremos apache2. Igualmente indicaremos SI cuando nos pregunte sobre configurar la base da datos para phpMyAdmin con dbconfig-common.



Después nos preguntarán una contraseña para phpMyAdmin. Podemos dejarla en blanco ya que el programa establecerá una aleatoria y nosotros no la necesitaremos el resto del tutorial. Si posteriormente queremos acceder a la base lo haremos con la contraseña del usuario 'root' que configuraremos luego. 

Finalmente, cuando haya terminado necesitamos editar una línea para indicarle a Apache que hemos instalado PHPMyAdmin. Para ello:

> sudo nano /etc/apache2/apache2.conf

y añadiremos el final de este archivo lo siguiente:

Include /etc/phpmyadmin/apache.conf

Una vez realizado, salvamos presionado CTRL + X y pulsamos Y para aceptar los cambios.

Reiniciamos Apache:

> sudo service apache2 restart

y comprobamos que se ha instalado correctamente accediendo a la siguiente url desde nuestro navegador en la Raspberry Pi http://localhost/phpmyadmin o bien desde otro equipo de la misma red con http://direción_IP_PI/phpmyadmin. Deberíamos ver algo similar a:

phpmyadmin, página de bienvenida en Raspberry pi

5) Configurar la base de datos de wordpress

Procedemos a configurar la base de datos antes de iniciar wordpress.

> sudo mysql_secure_installation 

Vamos contestando a las preguntas que nos hace el programa.

1 pregunta cofiguracion mysql_sevure_installation

Lo primero que nos dicen es que pongamos la contraseña root de la base de datos, pero como acabamos de instalarla aun no tiene ninguna contraseña así que le damos un intro para dejarla en blanco.

A continuación si que ya ponemos una contraseña para el usuario root de la base de datos , seleccionando "yes" en la pregunta de que si queremos contraseña y la confirmamos.


introducion de contraseña de root


A todas las demás preguntas que nos haga las dejamos en la opción por defecto dándole al intro.


5.a. Creamos la base de datos para wordpress con:

> sudo mysql -uroot -p

Lógicamente usamos la contraseña que elegimos antes.

Luego  vamos a crear una base de datos que se llamará wordpress, y le damos privilegios para poder acceder a ella al usuario 'root':

MariaDB [(none)]> create database wordpress;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON wordpress.* TO 'root'@'localhost' IDENTIFIED BY 'PASSWORD';

Importante: sustituye la palabra PASSWORD por la contraseña que le hayas puesto al usuario 'root'.

MariaDB [(none)]> FLUSH PRIVILEGES;

Salimos del programa pulsando ctrl + d.


6.) Entramos en Wordpress y acabamos de rematar el proceso.

Ahora que lo tenemos todo preparado es hora de entrar en Wordpress. Para ello como hemos hecho hasta ahora, en un navegador acedemos al localhost o si como en mi caso lo estas haciendo desde otro equipo usamos la dirección Ip de la Rapsberry en nuestra red. Nos aparecerá la página de configuración inicial de Wordpress.

pagina de elección de idioma de wordpress

Escogemos el idioma de la aplicación que queremos y le damos a continuar. Nos aparecerá la pantalla de Bienvenida.

Pantalla de bienvenida de wordpress


Ya en la siguiente pantalla tenemos que poner los datos de configuración de la base de datos que usará wordpress y que ya hemos creado antes.


configuración de base de datos de wordpress


Cambia la contraseña por la que hayas asignado antes al usuario 'root'. Si todo ha ido bien wordpress se podrá conectar con éxito a la base de datos  y ya casi habremos terminado.

pantalla final de la instalación de wordpress


Ya solo nos queda elegir un nombre para nuestro sitio web, elegir un nombre de usuario y una contraseña (recuerda ambos que sino luego no podrás entrar) y poner nuestro correo electrónico.

información necesaria para acceder a wordpress


Cuando hayas terminado el programa de instalación nos dirá que ha finalizado y a continuación ya aparecerá la página para logearnos en wordpress y poder empezar a crear nuestro sitio web.

pantalla de login en wordpress

y con esto ya habremos terminado. 

Vista web de la página de administración de Wordpress


Y mientras tengas la rapsberry pi encendida tu sitio web estará disponible y en funcionamiento. 



miércoles, 12 de mayo de 2021

Apendice. Uso de MySql o MariaDB en un proyecto Flask.




La base de datos que he usado durante el desarrollo del proyecto está muy bien para aplicaciones simples, pero si queremos implementar un servidor web completo, que puede necesitar manejar multiples solicitudes a la vez, es mejor utilizar una base de datos más robusta. Por esa razón voy a explicar como configurar una base de datos de tipo MySql en concreto MariaDB.

MariaDb es una base de datos opensource basada en MySql y que es compatible con la misma.

Lo primero que haré será instalarlo. Para ello abrimos un terminal y comenzamos actualizando los repositorios:

$ sudo apt-get update
$ sudo apt-get full-upgrade

Una vez actualizado el software de la Raspberry, procedemos a instalar MariaDB:

$ sudo apt-get install mariadb-server 

Con esto ya tenemos instalado MariaDB. Ahora vamos a tratar de configurarlo. Para ello escribimos el siguiente comando:

$ sudo mysql_secure_installation

Este comando aunque se llame mysql se puede usar con MariaDB. Lo primero que nos pide es que escribamos nuestra contraseña actual, pero como acabamos de instalarla no tenemos ninguna por lo que simplemente le damos un Enter.



Luego nos pregunta si queremos establecer una contraseña para el usuario root. Yo no voy a ponerla con lo cual presiono "n". (pero tu puedes ponerla sin problemas)



A continuación nos pregunta si queremos eliminar los usuarios anónimos, lo que si vamos a hacer. Presionamos "y"



También nos pregunta si queremos desactivar el acceso remoto, a lo que contestamos que si ya que en nuestro proyecto todas las consultas a la base de datos se realizarán de forma local.



Nos preguntará si queremos eliminar la base de datos de prueba a lo que también contestamos que si. "y"



Y para finalizar nos dirá si queremos recargar los privilegios de la tabla ahora. Contestamos que si "y"



Y ya la tenemos configurada. Otra forma es dejar las opciones por defecto pulsando simplemente Enter a cada pregunta lo que viene a ser los mismo.



Para ver que versión tenemos instalada podemos teclear:

$ mysql --version



Bien ahora que ya lo tenemos preparado vamos a ejecutar MariaDB, 

$ sudo mysql



Este comando nos conecta con MariaDB y nos mostrará su prompt donde podemos crear base de datos, usuarios etc. 

Pero lo primero que tenemos que hacer es crear un usuario nuevo adicional con privilegios que es el que usaremos en nuestro proyecto. Ejecutaremos el siguiente comando:

MariaDB [(none)]> GRANT ALL ON *.* TO 'usuario'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;





En donde 'usuario' es el nombre del nuevo usuario que utilizaremos en nuestra base de datos.

En donde 'localhost' es la dirección de red de la base de datos, en nuestro caso al trabajar en local usaremos localhost.

En donde 'password' es la contraseña del usuario para la base de datos.

Voy a comprobar si todo ha quedado bien. Para ello reiniciamos la tabla para que pueda reconocer mi nuevo usuario.

MariaDB [(none)]> FLUSH PRIVILEGES;
Ahora ya podemos salir de la base de datos con:

MariaDB [(none)]> EXIT;
y testearemos si mariadb está ejecutándose  y el usuario ha quedado bien registrado.

$ sudo systemctl status mariadb







Vemos que el servicio mariadb esta activo y ejecutándose y si queremos saber más sobre el shell de MariaDB podemos usar:

$ sudo mysqladmin version




ffgfg

Vamos a testear nuestro nuevo usuario. Para ello nos volveremos a conectar con el nuevo usuario que hemos creado.

$ mysql -u usuario -p
Nos preguntará la contraseña que hemos definido antes y si todo ha ido bien, veremos algo como esto:








Y desde aquí ya podemos crear la base de datos que vamos a utilizar en el proyecto.

MariaDB [(none)]> create database mibase;
o si quieres crear la base de datos usando el juego de caracteres utf-8:

MariaDB [(none)]> CREATE DATABASE mibase CHARACTER SET utf8 COLLATE utf8_bin;
Nota: si te confundes de nombre de la base y quieres borrarla, si tienes permisos sobre ella puedes hacerlo con:

MariaDB [(none)]> DROP DATABASE nombre_de_la_base_a_borrar;  

Podemos ver si ha quedado correctamente creada usando el siguiente comando, que nos muestra las bases de datos que tiene asignadas mariadb:

MariaDB [(none)]> show databases;



En el post anterior de como desplegar una aplicación en raspberry pi hemos utilizado la aplicación del post 19 así que vamos utilizar ese ejemplo, para pasar de una base de datos sqlite que utiliza a MariaDB. 


IMPORTANTE: para que todo funcione correctamente tenemos que instalar un driver que haga de enlace o controle la base de datos MariaDB desde python. Esto es muy sencillo solo tenemos que instalar el  paquete pymysql dentro de nuestro entorno virtual.

Entramos en el entorno virtual de la aplicación de ejemplo:

pi@raspberry:~/miproyecto $ source ./miEntorno/bin/activate
e instalamos el siguiente paquete, que es el driver que nos va a servir de enlace:

(miEntorno) pi@raspberry:~/miproyecto $ pip install pymysql


Como ya vimos en el post 14 sobre Flask para dejar de usar sqlite y usar la base de datos que hemos creado tendremos que hacer unos sencillos pasos, además de instalar el driver que acabamos de  hacer.

1) En el archivo de configuración de nuestra aplicación (config.py) tenemos que cambiar el conector de sqlite y usar el conector de Mariadb.



Si usaste tu propio nombre de usuario, contraseña o nombre de la base de datos tendrás que modificarlo en el conector.

Los míos eran:

usuario = usuario
contraseña = password
nombre de la base de datos mariadb = mibase

2) Migración de la base de datos creada, pero no hemos adaptado su estructura a los campos que ya tenemos creados en la aplicación. Para eso tenemos que realizar una migración. Seguimos los siguientes pasos.

a) Instalamos, sino lo tenemos ya, el paquete flask-migrate

(miEntorno) $ pip install flask-migrate
Ahora tenemos que importarlo y declararlo en el archivo de la aplicación inicio.py.



Bien como nuestra aplicación inicial, no se llama app.py ni wsgi.py, tenemos que decirle a Flask, para que haga lo mostraré a continuación, cual es nuestra aplicación principal. Para ello solo tenemos que teclear lo siguiente:

(miEntorno) $ export FLASK_APP=inicio.py
Esto solo dura mientras tengas la sesión abierta, si la cierras y vuelves a entrar tendrás que teclearlo de nuevo.

Vamos al lio. Alembic (el framework de migración utilizado por Flask-Migrate) va a realizar los cambios en la estructura de la base de datos de forma que no tengamos que volver a crearla desde cero.  Pues bien, una vez que le hemos dicho a flask cual es nuestra aplicación principal tecleamos:

(miEntorno) $ flask db init
creating directory /14/migrations ...  done
  Creating directory /14/migrations/versions ...  done
  Generating /14/migrations/alembic.ini ...  done
  Generating /14/migrations/README ...  done
  Generating /14/migrations/env.py ...  done
  Generating /14/migrations/script.py.mako ...  done
  Please edit configuration/connection/logging settings in '/14/migrations/alembic.ini' before proceeding.

Después de haber ejecutado este comando te encontrarás un nuevo directorio en el directorio de trabajo llamado migrations con unos cuantos archivos y un subdirectorio llamado versions (que contendrá las modificaciones que hagamos a la estructura de la base de datos)

Cuando hagamos una migración, Alembic, comparará la estructura almacenada en sus directorios con la actual que tengamos definida en nuestro programa y realizará los cambios. Como esta es la primera vez que ejecutaremos el comando y previamente no hay nada, lo que hará será crear tanto el archivo de la base de datos como su estructura. Y lo creará en el directorio y con el nombre que hayamos especificado dentro del archivo de configuración del proyecto, en nuestro caso en:

# Cadena de conexion
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://usuario:password@localhost/mibase'
b) Realizamos la migración. Nos situamos en el mismo directorio donde está inicio.py, si no estamos ya, y tecleamos:

(miEntorno) pi@raspberry:~/miproyecto $ flask db migrate -m "migracion mariaDB"
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'usuario'
  Generating
  /home/pi/miproyecto/migrations/versions/2fa6cb75c75d_migracion_mariadb.py ...  done
El programa acaba de generar un script para poder migrar la base de datos con un identificador único 2fa6cb75c75d (en tu caso será otro distinto). El comentario de la opción -m es opcional y añade una breve descripción de texto a la migración.

c) Consolidar la migración. 

(miEntorno) pi@raspberrry:~/miproyecto $ flask db upgrade
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 2fa6cb75c75d, migracion mariaDB

Y listo ya tenemos nuestra base de datos, mibase, con sus tablas y sus registros preparados y listos para trabajar. 


Instalar phpMyadmin para gestionar nuestra base de datos MariaDB.

PhpMyAdmin es una herramienta escrita en php con la intención de poder manejar bases de datos de tipo Mysql a través de páginas web, utilizando un navegador web. Con el podemos hace de todo en la base de datos mysql de una forma visual.

 Actualmente puede crear y eliminar Bases de Datos, crear, eliminar y alterar tablas, borrar, editar y añadir campos, ejecutar cualquier sentencia SQL, administrar claves en campos, administrar privilegios, exportar datos en varios formatos y está disponible en 72 idiomas

El método para realizar la instalación, es tener primero tanto el apquete mariadb-server como maríadb-client. Luego podemos instalar phpmyadmin con el siguiente comando:

  • $ sudo apt-get install phpmyadmin

Durante la instalación nos preguntará que servidor queremos utilizar para sevir las páginas si apache o ligthtpd. Si quieres usar nginx también se puede. Puedes conseguir información en esta web.

Si todo ha ido correcto al ir al navegador y teclear:

https://nombredelservidor_or_IP/phpmyadmin



Deberías ver la pantalla de bienvenida y a partir de ahí con el usuario que hemos definido previamente poder entrar en la aplicación.

Puedes encontrar más información sobre instalar phpMyAdmin es el blog "usuariodebian.blogspot.com"

Código del Capitulo en GitHub. Ten en cuenta que la base de datos mibase no está incluida tienes que crearla tu y cambiar el conector por el nombre de tu usuario y contraseña ya que se partio en el ejemplo de una base sqlite3.


Próximo Capítulo. Desplegar una aplicación de Flask en Heroku.

viernes, 21 de agosto de 2020

Flask 14. Usando una base de datos en Flask, Flask-SQLAlchemy

 

Base de datos azul icono vector de la imagen | Vectores de dominio ...


Usando una base de datos en Flask, Flask-SQLAlchemy


Anteriormente. Flask 13. Subiendo archivos al servidor con Flask-WTF.


https://flask-sqlalchemy.palletsprojects.com/en/2.x/

Flask- SQLALchemy es un ORM (Object Relational Mapper) o lo que es lo mismo, un módulo que nos permite interactuar con una base de datos SQL sin preocuparnos por la sintaxis de SQL, es decir vamos a poder crear, leer, actualizar y borrar datos (CRUD en inglés) simplemente utilizando métodos de python y no del lenguaje de programación de la base de datos en concreto. Esto nos va a permitir trabajar con objetos y no con tablas y SQL. 

Otra ventaja es que podemos utilizar diferentes bases de datos: sqlite3, mysql o postgreSql sin tener que modificar prácticamente nuestra aplicación. Esto nos permite, por ejemplo, que mientras creamos la aplicación estemos trabajando con sqlite3 y cuando terminemos el proyecto pasar a una base de datos MySql sin tener que prácticamente modificar el programa.


Instalación de Flask-SQLAlchemy


Si estas usando un entorno virtual, entra en él y teclea:

pip install Flask-SQLAlchemy

En todos los capítulos anteriores las variables que podíamos configurar en Flask (debug=True o secret_key, por ejemplo) estaban dentro de nuestra aplicación principal, inicio.py. A partir de este momento vamos a crear un archivo solamente para guardar todo lo que tengamos que configurar, lo que nos va a resultar mas cómodo.

Configuración de Inicio.py para usar FLask-SQLAlchemy


Todos los parámetros de configuración de la aplicación van a estar en un nuevo archivo. Lo puedes llamar como quieras, yo le llamaré "config.py". Estará dentro de nuestro directorio de trabajo al mismo nivel que inicio.py. Quedaría de la siguiente forma:

Código de configuración del archivo config.py. Se puede encontrar el código al fina del cápitulo
Código archivo config.py

  • SECRET_KEY: Los utilizaremos para cifrar los tokens para el mecanismo de seguridad csrf en los formularios.

  • PWD: es una variable que contendrá el directorio de trabajo de la aplicación. Previamente habíamos importado el modulo standar de python os. Ahora lo utilizamos para que nos devuelva la ruta absoluta de nuestro directorio de trabajo. Algo así en Linux como: '/home/usuario/Escritorio/Flask/Aplicacion'. Luego lo utilizaremos para indicar al programa, donde está nuestra base de datos.

  • DEBUG=True: para inicializar el depurador del servidor y poder hacer y ver cambios sobre la marcha.

  • SQLALCHEMY_DATABASE_URI: indicamos la dirección de la base de datos con la que se realizará la conexión o con la que vamos a trabajar. Su estructura dependerá del tipo de base de datos que vayamos a usar. En estos ejemplos vamos a usar sqlite3 con lo que utilizamos: 'sqlite:///{}/database/dbase.db'.format(PWD). Es decir, le decimos que busque la base de datos "dbase.db" en el directorio database. 
Pero no te preocupes, aun no tenemos nada creado, solo le hemos dicho donde encontrar la base de datos en el futuro, pero te repito, aun no tenemos nada creado. La estructura final quedaría:
    Directorio de trabajo / database / dbase.db 


    Ahora si, para que todo este más ordenado crea una carpeta llamada "database", que de momento dejarás vacía, y donde más adelante crearemos la base de datos con el nombre de dbase.db. Si utilizáramos otro tipo de base de datos, por ejemplo mysql, la estructura del URI sería algo así como: mysql://username:password@server/db


    Básicamente, este comando es el que variará dependiendo de si usamos sqlite3 u otro tipo de base de datos. Nada más. El resto del código permanecerá prácticamente igual. Esta es la ventaja de usar sqlalchemy.

    • SQLALCHEMY_TRACK_MODIFICATIONS: deshabilitamos la gestión de notificaciones de sqlalchemy.

    Este fichero, config.py,  lo utilizaremos en inicio.py para cargar las variables de configuración. ¿Cómo haremos esto? Pues importando el modulo config que acabamos de crear y utilizando la siguiente instrucción:

    app.config.from_object(config)

    Aunque también puedes no importar config, siempre que este al mismo nivel que inicio.py y usar:

    app.config.from_object('config')

    Lo mismo que antes pero con las comillas.

    En este capítulo optaré por la primera opción.

    Además en el programa principal vamos a crear un objeto que represente a nuestra base de datos.

    db = SQLAlchemy(app)


    Con todo lo anterior, el archivo inicio.py quedaría:



                                            from flask import Flask
                                            import config
                                            from flask_sqlalchemy import SQLAlchemy
                                            app = Flask(__name__)
                                            app.config.from_object(config)
                                            db = SQLAlchemy(app)


                                            @app.route('/')
                                            def home():
                                                return 'esto es la página de inicio'


                                            @app.errorhandler(404)
                                            def page_not_found(error):
                                                 return "pagina no encontrada", 404


                                            if __name__ == '__main__':
                                                app.run()



    Diseño y creación del modelo de base de datos.


    Para seguir avanzando en los conceptos de este tema vamos hacer una pequeña y sencilla aplicación. Imaginemos que tenemos una pequeña empresa y que necesitamos una aplicación para llevar el registro de nuestros empleados. De cada empleado vamos a registrar:
    • El nombre
    • Un correo electrónico
    • Un teléfono.

    Un inciso.

    En la parte de diseño para que no quede tan simple he utilizado bootswatch que es como bootstrap pero con plantillas ya prediseñadas de diversos colores. He escogido el tema Sketchy. Esta cargado en nuestra plantilla base antes de cualquier otro CSS. 

    Puedes hacerlo de dos formas:

    1.- Le das al botón Download y descargas el script en local. Luego pones donde esta el archivo en <link rel="stylesheet" href="ruta del archivo descargado"> 
    2.- Te pones encima del botón Download y con el botón derecho seleccionas "Copiar dirección de enlace" y la pegas dentro de <link rel="stylesheet" href="Pegar el enlace aquí">

    Para el degradado de fondo he utilizado uiGradients cargado en la etiqueta <body>.

    Continuamos. 

    Vamos a modelar la base de datos que vamos a necesitar, para que contenga los campos (id, nombre, correo y teléfono). En inicio.py ponemos el código justo después de crear el objeto db y antes de las  vistas. 

    Vamos a comentarlo:

                    15     class Empleados(db.Model):
                    16         '''Tabla de datos de los empleados de la empresa'''
                    17        __tablename__ = 'empleados'
                    18         id = db.Column(db.Integer, primary_key=True)
                    19         nombre = db.Column(db.String(50), unique=True, nullable=False)
                    20         correo = db.Column(db.String(30), unique=True, nullable=False)
                    21         telefono = db.Column(db.Integer)
                    22
                    23         def __repr__(self):
                    24             return f'<Empleado {self.nombre}>'


    En la línea 15 creamos una clase que heredara de db.Model y que llamaremos Empleados. Eso nos permitirá modelar la base de datos. Dentro de la clase definiremos todos los campos que están relacionados con los empleados: El id o referencia del empleado, el nombre, correo electrónico y teléfono.

    En la variable __tablename__ indicamos el nombre de la tabla a la que corresponde esta clase. Por defecto Flask-SQLAlchemy se referirá a nuestra tabla con el nombre de la clase en minúsculas y separando las palabras con un guion bajo. En nuestro caso, por tanto, daría igual ponerlo que no, pero he preferido hacerlo para que se vea como ejemplo. 

    Indicaremos los distintos campos que necesitaremos usando el constructor db.Column y dentro definimos los distintos tipos de datos que se pueden guardar. 

    Entre otros puedes usar los siguientes:

    - Boolean - para guardar tipos de dato de tipo Boleano. Como valores del parámetro admite None, True, False, 0 o 1.

    - DateTime - para guardar la fecha y hora devuelto por el modulo de python datetime.

    - Float - para guardar números de coma flotante.

    - Integer - para guardar números enteros.

    - String - para guardar cadenas de tipo string: texto, caracteres etc. Le puedes pasar como primer parámetro el número máximo de caracteres que acepta el campo "db.Column(db.String(max.caracteres)" o puedes conseguir lo mismo con un parámetro usando "length = max. caracteres."

    - Text - muy parecido al anterior. No se puede especificar el tamaño máximo del campo, tiene una longitud de string variable.

    Puedes indicar que el campo tenga un valor por defecto si no se indica otro. Por ejemplo un campo numérico que tenga un valor de 0 sería:

    db.Column(db.Integer, default=0)

    Además del tipo de datos podemos indicar entre otros los siguiente atributos de cada campo

    primary_key automáticamente se crea al generar un registro para diferenciar a cada registro. 
    - unique o campo único que no puede haber otro de igual contenido en la tabla. 
    - nullable - Si su Valor es False obliga a que el campo siempre tenga un valor, no puede ser nulo.
    - index - Si especificamos que el campo este indexado con index=True, esto acelerará y hará que sean más eficientes las búsquedas por ese campo.
     
    Al final utilizamos def __repr__(self) para obtener una representación legible del objeto Empleado.

    Estarás pensando...¿y donde o cuando hemos creado el archivo con la base de datos? Pues hasta ahora en ningún sitio. Solo hemos diseñado la clase que contendrá la base de datos y creado el directorio "database". Si recuerdas, en el archivo config.py le dijimos a la base de datos que esta se llamaría dbase.db y estará en el directorio database al mismo nivel que la aplicación principal. Esto lo hicimos con la instrucción:

    SQLALCHEMY_DATABASE_URI = 'sqlite:///{}/database/dbase.db'.format(PWD)

    Ha llegado el momento de crear la base de datos. Para ello tenemos que estar dentro del directorio de trabajo que contiene nuestros archivos y ejecutar el shell de python, importar db del modulo inicio y ejecutar db.create_all(). 

                        julian@ubuntu:~/Escritorio/Flask/14$ source ../miEntorno/bin/activate
                        (miEntorno) julian@ubuntu:~/Escritorio/nFlask/14$ python
                        Python 3.6.9 (default, Jul 17 2020, 12:50:27) 
                        [GCC 8.4.0] on linux
                        Type "help", "copyright", "credits" or "license" for more information.
                        >>> from inicio import db
                        >>> db.create_all()
                        >>> 
    Nota: si esta usando un entorno virtual entra primero dentro del mismo.

    IMPORTANTE:

    1º) Nuestra aplicación esta trabajando con SQlite, por lo que al ejecutar el código anterior, este detecta que la base de datos no existe aún y la crea. Sin embargo, cuando trabajes con servidores de bases de datos como MySQL y PostgreSQL, tendrás que crear tu la base de datos en el servidor de la base de datos.

    2º) Estás instrucciones no actualizan la estructura de la base de datos si cambiamos el modelo. Por ejemplo si a posteriori añades un campo más a los anteriores, por ejemplo un campo llamado "salario", tendrías que borrar las tablas y crearlas de nuevo usando las instrucciones:

    from inicio import db
    db.drop_all()
    db.create_all()

    Podemos utilizar también la migración de base de datos que te permite, al cambiar el modelo actualizar la estructura de la base de datos. Para trabajar con migraciones puedes usar la extensión Flask-Migrate.

    *** Aquí voy a hacer un paréntesis en este capítulo y explicar un poco como funciona esta extensión. Aunque en el código de esta página no lo voy a utilizarlo, me parecía interesante verlo para futuros proyectos. El texto del capítulo continua después de lo que está entre las dos líneas amarillas. Si no te interesa este paquete o simplemente quieres seguir con el capítulo sin interrupciones, puedes saltártelo.


    --------------------------------------------------------------------

    Como siempre, para utilizar flask-migrate, lo primero que tenemos que hacer es entrar en nuestro entorno virtual e instalarlo con:

    (venv) $ pip install flask-migrate
    luego si queremos utilizarlo tenemos que importarlo y declararlo en el archivo inicio.py de esta forma, una vez que hemos creado la estructura de la base de datos con la clase Empleado y hemos creado antes app y db:




    Bien como nuestra aplicación inicial, no se llama app.py ni wsgi.py, tenemos que decirle a Flask para que haga lo mostraré a continuación, cual es nuestra aplicación principal. Para ello solo tenemos que teclear lo siguiente:

    (venv) $ export FLASK_APP=inicio.py

    Esto solo dura mientras tengas la sesión abierta, si la cierras y vuelves a entrar tendrás que teclearlo de nuevo. Aprovecho esto para decirte que hasta ahora habíamos ejecutado el programa lanzándolo con el interprete de python tecledando:

    (venv) $ python inicio.py
    Pero si declaras cual es la aplicación principal en Flask también puedes lanzarlo con:

    (venv) $ flask run
    dicho lo cual volvemos al tema de la base de datos. La clase Empleados que hemos creado anteriormente define la estructura inicial de nuestra base de datos para esta aplicación. Pero cuando la aplicación siga creciendo es muy normal que haya cambios en la misma. Podemos añadir nuevos campos, añadir más tablas, borrar algún campo etc.

    Alembic (el framework de migración utilizado por Flask-Migrate) hará estos cambios en la estructura de la base de datos de forma que no tengamos que volver a crearla desde cero.  Pues bien, una vez que le hemos dicho a flask cual es nuestra aplicación principal tecleamos:

    (venv) $ flask db init
    creating directory /14/migrations ...  done
      Creating directory /14/migrations/versions ...  done
      Generating /14/migrations/alembic.ini ...  done
      Generating /14/migrations/README ...  done
      Generating /14/migrations/env.py ...  done
      Generating /14/migrations/script.py.mako ...  done
      Please edit configuration/connection/logging settings in '/14/migrations/alembic.ini' before proceeding.
    

    Después de haber ejecutado este comando te encontrarás un nuevo directorio en el directorio de trabajo llamado migrations con unos cuantos archivos y un subdirectorio llamado versions (que contendrá las modificaciones que hagamos a la estructura de la base de datos)

    Cuando hagamos una migración, Alembic, comparará la estructura almacenada en sus directorios con la actual que tengamos definida en nuestro programa y realizará los cambios. Como esta es la primera vez que ejecutaremos el comando y previamente no hay nada, lo que hará será crear tanto el archivo de la base de datos como su estructura. Y lo creará en el directorio y con el nombre que hayamos especificado dentro del archivo de configuración del proyecto, en nuestro caso en:

    SQLALCHEMY_DATABASE_URI = 'sqlite:///{}/database/dbase.db'.format(PWD)

    Vamos a ello:

    (venv) $ flask db migrate -m "primera migracion"
    /14
    INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
    INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    INFO  [alembic.autogenerate.compare] Detected added table 'empleados'
      Generating /14/migrations/versions/0dd11e9faf8b_primera_migracion.py ...  done
    

    El programa acaba de generar un script para poder migrar la base de datos con un identificador único 0dd11e9faf8b (en tu caso será otro distinto). El comentario de la opción -m es opcional y añade una breve descripción de texto a la migración.

    Ahora podemos hacer dos cosas:

    1) Aplicar la función upgrade() que aplicará la migración, con todas sus modificaciones
    2) Si nos hemos confundido o no nos interesa hacerla podemos aplicar la función downgrade() y eliminaremos los cambios y volveremos al punto anterior.

    Como queremos consolidar los cambios utilizaremos upgrade de esta forma:

    (venv) $ flask db upgrade
    /14
    INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
    INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    INFO  [alembic.runtime.migration] Running upgrade  -> 0dd11e9faf8b, primera migracion
    
    Y listo ya tenemos nuestra base de datos, dbasedb, con sus tabla y sus registros preparados y listos para trabajar. En resumen, para crear o actualizar la estructura de nuestra base de datos tenemos que primero generar el script de migración con flask db migrate y posteriormente consolidarla con flask db update.

    El utilizar flask-migrate, es muy útil porque si por ejemplo tienes el mismo proyecto en dos ordenadores, una vez generado el script de migración en el primero "flask migrate", lo puedes copiar y llevar al otro y automáticamente cuando apliques el upgrade en el segundo consultara sus versiones, verá si la que le has puesto es la más actual y aplicará los cambios.


    --------------------------------------------------------------------


    Bien, hecha la matización, volvemos a la rama principal de este capítulo. 

    Si ahora miras dentro del directorio database, SORPRESA, deberías ver como se ha creado el archivo dbase.db. Por si te sirve yo estoy usando para verlo un gestor de base de datos llamado "DB Browser for SQlite"

    Pagina Principal de la Aplicación.


    Lo primero que veremos nada mas entrar en la aplicación, va a ser nuestra pantalla principal. Tendrá un aspecto como este:


    La vista inicial estará formada por el siguiente código:


    Asignamos todos los registros que tenemos en la base de datos a la variable empleados con la instrucción Empleados.query.all() y se la pasamos a la plantilla main.html.

    Esta plantilla tendrá un botón en la parte superior derecha que nos permitirá añadir un nuevo empleado. Al pulsarlo nos redirigirá a la dirección o vista create.html


    Por otra parte, en la plantilla principal "main.html" y través de una tabla, vamos a usar un bucle {% for ...%}{% endfor %} para recorrer todos los registros de la base de datos que le hemos pasado en la variable empleados, con sus correspondientes campos (nombre, teléfono y correo electrónico)



    Además como última columna añadimos dos botones para poder "Editar" o "Borrar" cada registro. Tienes el código completo al final del capítulo.

    Añadir registros a la base de datos.


    Lo primero que he hecho es crear un formulario, con los archivos form.py y create.htlm, donde se recojerán los datos que necesitamos. Como ya hemos visto como se crean y usan los formularios, no voy a pararme a explicarlo. Puedes encontrar el código al final del capitulo y ver el post correspondiente a crear formularios.

    Quedará de la siguiente forma:



    Vamos a centrarnos en la vista. 

                                        @app.route('/create/', methods=["GET", "POST"])
                                            def create_item():
                                                form = Crear_Registro()
                                                if form.validate_on_submit():
                                                    # empleado es una instancia de la clase Empleado
                                                    empleado = Empleados(
                                                        nombre=form.nombre.data,
                                                        correo=form.correo.data,
                                                        telefono=form.telefono.data)
                                                    try:
                                                        db.session.add(empleado)
                                                        db.session.commit()
                                                        return redirect(url_for('home'))
                                                    except:
                                                        return 'ha habido un problema'
                                                else:
                                                    return render_template('create.html', form=form)


    Creamos la ruta "/create/" y definimos la función para guardar nuestros registros create_item 

    Al pulsar en el botón de la pagina principal "Añadir nuevo empleado" nos redirigirá a esta vista. Entraremos usando el método GET con lo que se renderizará la plantilla create.html en donde le hemos pasado el formulario.

    Cuando el formulario este relleno y validado se mandará a la ruta usando el método POST. De ahí, creamos la variable empleado, instancia de la clase Empleados, que recogerá los valores de los campos enviados en el formulario (nombre, correo y teléfono).  El id no lo pasamos porque automáticamente lo va a crear la base de datos cuando añadamos los registros.

    En flask-SQLAlchemy, para guardar un objeto en la base de datos, este debe estar previamente asociado al objeto sessión. Por tanto para añadir un nuevo empleado a la base de datos, lo haremos con db.session.add(). Simplemente le pasamos  los campos que queremos añadir que ya están metidos en la variable empleado, en singular, que ahora mismo es un objeto de la clase Empleados. 

    Bien, le hemos dicho a la base de datos que queremos añadir un registro pero como en toda base de datos tenemos que consolidarla, sino quedará sin hacer. Esto se consigue con la instrucción db.session.commit()

    Si todo ha ido bien volverás a la página de inicio "return redirect(url_for('home')" con el nuevo empleado ya guardado en la base de datos. Y como la página principal se encarga de listar todos nuestros empleados este registro se mostrará automáticamente.

    Borrar registros de la base de datos.


    Cada empleado en la página principal tiene un botón rojo a la derecha que nos permitirá borrarlo de la base de datos. 

    Al pulsarlo te saldrá un mensaje de advertencia para confirmar la acción. 


    Esto se consigue en main.html usando el atributo: onclick="return confirm('¿Estás seguro de querer borrar el registro?')" en la etiqueta <a> que usamos para crear el botón.

    Un punto importante es que al usar este botón, este nos redireccione a una vista que nos permita borrar ese empleado en concreto, para lo cual tendremos que indicar el id del mismo como parámetro. Por ejemplo si sitúas el ratón sobre el botón borrar del empleado cuyo Id es igual a 2, y te fijas en la parte inferior izquierda de la pantalla, veras que nos esta indicando la url a la que nos redirigirá cuando lo pulsemos.

    Pej. 127.0.0.1:5000/delete/2/

    Es decir enviamos 2 como parámetro a la URL /delete/. Para conseguir esto, cuando en main.html diseñamos el botón de cada registro, dentro del bucle for  tenemos que utilizar:

    <a href="{{url_for('delete_item', id=item.id)}}">
    o
    <a href="/delete/{{item.id}}/"

    Para que esto funcione tenemos que diseñar también la vista /delete/ para que acepte un parámetro, el id, que será un número entero.




    Una vez que tenemos la id del registro borrarlo es muy sencillo. Creamos primero la función delete_item, al que tenemos que pasarle el parámetro id y una variable empleado que recoja el resultado de buscar un registro dentro de Empleados filtrado por su campo id y lo ordenamos que lo borre:

    empleado = Empleados.query.filter_by(id=id).delete()

    y confirmamos el cambio:

    db.session.commit()

    Una vez hecho lo anterior volverá a la pagina principal (home) donde ser volverán a renderizar todos los registros actualizados de la base de datos.


    Actualización de un registro existente en la base de datos.


    La forma de hacerlo es parecida a la del punto anterior. Empezamos programando el botón amarillo para editar el registro en la pantalla principal. Al pulsarlo nos tiene que enviar a la URL /update/ enviando como parámetro el numero de id. Para editar por ejemplo el empleado con id=2 sería:

    127.0.0.1/update/2

    El código del botón quedaría en main.html como:

    <a href="{{url_for('update_item', id=item.id)}}">
    o
    <a href="/update/{{item.id}}>

    La vista en el inicio.py:



    La primera vez que entramos en la vista, lo hacemos usando el metodo GET y le pasamos el id del registro. Buscamos los datos del empleado asociado al id enviado con:

    empleado = Empleados.query.filter_by(id=id).first()

    Al usar filter_by() necesitamos decirle que registro queremos seleccionar. Aunque en este caso solo hay uno, ya que el id del empleado es único, tenemos que especificar que el primero .first()

    Luego renderizamos la plantilla 'update.html' enviando un formulario y el id. El formulario es el mismo que creamos para introducir un nuevo empleado con el matiz de que le pasamos, no un formulario vacío esta vez, sino que lo rellenamos con los datos que hemos obtenido con la consulta a la base de datos.



    Ahora modificamos lo que queramos en el formulario y le damos a enviar.  El formulario se enviará a la Url anterior volviendo a enviar de vuelta como parámetro el id y esta vez con el método POST.

    <form action="{{url_for('update_item', id=id)}}" method="post">

    Como el formulario ha sido validado y enviado, el condicional form.validate_on_submit() será verdadero y se ejecutará el código de su interior.

    Volvemos a buscar el empleado cuyo id se corresponde con el enviado por el formulario. Esta vez lo podemos hacer de otra forma con, por ejemplo:

    empleado = Empleados.query.get(id)

    e identificamos cada campo de la base de datos del empleado (nombre, correo y teléfono), con lo obtenido del formulario.

                                                empleado.nombre = form.nombre.data
                                                empleado.correo = form.correo.data
                                                empleado.telefono = form.telefono.data

    y ya lo tenemos, solo nos queda consolidarlo y listo.

    db.session.commit()

    Volveremos a la página inicial con el dato ya modificado.