lunes, 2 de enero de 2023

6.- Django - Bases de Datos.

Se supone que ya sabes que es una base de datos, tablas, registros etc 

Para ver este tema vamos a simular que creamos una tienda virtual. Empezaremos un nuevo proyecto independiente del que ya teníamos. Tecleamos:

$ django-admin startproject tiendaVirtual

Entramos dentro de la carpeta del nuevo proyecto creado:

$ cd tiendaVirtual

En este tema vamos a trabajar con varias aplicaciones que aunque están relacionadas van a hacer cosas distintas. Empezaremos creando una aplicación a la que llamaremos "gestiónPedidos". Django pude trabajar con diferentes aplicaciones independientes. Podríamos tener una aplicación para "Gestión de Almacén", otra para "Cobros y Pagos", otra para "Clientes" y así sucesivamente. 

En los capítulos anteriores no utilizamos Aplicaciones para nada, pero en la mayoría de los proyectos se requiere modularización  y usar a la vez diferentes aplicaciones.

Creamos la nueva aplicación:

tiendaVirtual$ python manage.py startapp gestionPedidos

Esto ha creado un nuevo directorio en nuestro proyecto:

Nueva aplicación creada

Si entramos en el, podemos ver los siguientes archivos:

archivos creados con la aplicacion


Una vez que hemos creado la primera aplicación, vamos a ver como crear las bases de datos. La clave está en el archivo models.py. Se trata de crear dentro de este archivo una clase por cada tabla que necesites que tenga tu base de datos. Cada clase hereda de models.Model. Lo bueno será que no tenemos que usar ni una sola instrucción de SQL todo esto lo hace por detrás DJANGO. 


models.py: Creación de tablas y campos.

from django.db import models

# Create your models here.

# Las tablas se crean mediante clases.

class Clientes(models.Model):
    # Dentro de la clase se crean los diferentes campos.
    nombre = models.CharField(max_length=30)
    direccion = models.CharField(max_length=50)
    # Email ya valido ya esta creado
    email = models.EmailField()
    telefono = models.CharField(max_length=9)

class Articulos(models.Model):
    nombre = models.CharField(max_length=30)
    categoria = models.CharField(max_length=20)
    precio = models.IntegerField()

class Pedidos(models.Model):
    numero = models.IntegerField
    fecha = models.DateField()
    entregado = models.BooleanField()
Hemos creado tres tablas Clientes, Artículos y Pedidos. 

En la tabla Clientes cada registro tendrá tres campos:
- nombre (campo de texto)
- dirección (campo de texto)
- email (es un tipo de campo ya preparado para aceptar emails válidos)
- teléfono (campo de texto)

En la tabla Artículos registraremos:
- nombre (campo de texto)
- categoría (campo de texto)
- precio (campo numérico)

En la tabla Pedidos registraremos:
- número de pedido (campo numérico)
- fecha (campo de fecha)
- si esta entregado o no (campo boleano)

 En el siguiente enlace puedes ver los diferentes tipos de campos que existen:


METADATOS.

Los metadatos en una tabla es "cualquier cosa que no es un campo o columna", cosas como la froma de ordenación de los registros (ordering), nombres de las tablas en la base de datos (db_table), o nombres que los humanos podamos entender tanto en singular como plural para los campos (verbose_name y verbose_name_plural).

Puedes encontrar una lista de las posibles opciones para la clase Meta en "model option reference" de la documentación de Django.

Vamos a ver algunos ejemplos.

Si cuando hagamos una consulta (query) a la base de datos queremos que los datos se muestren ordenados en base a un determinado campo usaremos la opción "ordering" de la clase Meta. Por ejemplo, si cuando consultemos la tabla "Clientes" queremos que estos se ordenen alfabéticamente podemos usar la clase Meta dentro de la clase Clientes de la siguiente forma:

models.py: Creación de tablas y campos.

from django.db import models

# Create your models here.

# Las tablas se crean mediante clases.

class Clientes(models.Model):
    # Dentro de la clase se crean los diferentes campos.
    nombre = models.CharField(max_length=30)
    direccion = models.CharField(max_length=50)
    # Email ya valido ya esta creado
    email = models.EmailField()
    telefono = models.CharField(max_length=9)
    
    class Meta:
        ordering = ["nombre"]

...
Si en vez de que aparezcan ordenados en orden ascendentes queremos que aparezcan en orden descendente usaremos un menos delante del nombre del campo. 

ordering = ["-nombre"]

También utilizando metadatos podemos crear un índice para la base de datos. Como realizaremos muchas consultas a la base de datos, consultando el número del pedido, vamos a indexar la tabla "Pedidos" en función de este campo. Esto mejorará el rendimiento de las consultas que realicemos ordenando o filtrando los datos por este campo.

models.py: Creación de tablas y campos.

from django.db import models

# Create your models here.

# Las tablas se crean mediante clases.

...

class Pedidos(models.Model):
    numero = models.IntegerField
    fecha = models.DateField()
    entregado = models.BooleanField()

    class Meta:
        indexes = [models.Index(fields=["numero"]),]



Ya tenemos la primera aplicación y modelo (3 tablas) y unos metadatos. El siguiente paso es decirle a nuestro proyecto de DJANGO que hay una aplicación nueva, porque hasta ahora no lo sabe. Hay que regístralo en "settings.py" dentro de la carpeta "tiendaVirtual". 

Ahí hay una sección llamada "INSTALLED_APPS"
que por defecto tiene todas las aplicaciones de Django existentes por el solo hecho de crearlo.  Ahí añadiremos el nombre de la aplicación:

tiendaVirtual/settings.py: Registro de aplicaciones.

...
ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'gestionPedidos',
]

MIDDLEWARE = [
...
Guardamos y a modo de prueba podemos teclear el siguiente comando para ver si todo esta bien. La siguiente salida es que el proyecto esta correctamente registrado:

/DJANGO/tiendaVirtual$ python manage.py check gestionPedidos
System check identified no issues (0 silenced).
Para crear la base de datos, con las tres tablas:

python manage.py makemigrations nombre_aplicación
Realizará la migraciones solo de esta aplicación o también puedes usarla sin el nombre de la aplicación con lo que comprobará todas las aplicaciones y realizará las migraciones en todas las tablas del proyecto.


/tiendaVirtual$ python manage.py makemigrations gestionPedidos
Migrations for 'gestionPedidos':
  gestionPedidos/migrations/0001_initial.py
    - Create model Articulos
    - Create model Clientes
    - Create model Pedidos
0001 - número de migración.

Pero ¡ojo! porque esto crea la base de datos y le dice a Django lo que debería tener la base de datos en su interior pero si miramos dentro con cualquiera de los programas que existen para ello, veremos que esta vacía.

Si tienes curiosidad de como se creará la tabla con instrucciones del código SQL puedes usar la siguiente instrucción aunque no es obligatoria, solo si tienes curiosidad de ver el código, que posteriormente se aplicará al realizar la migración.

/tiendaVirtual$ python manage.py sqlmigrate gestionPedidos 0001
BEGIN;
--
-- Create model Articulos
--
CREATE TABLE "gestionPedidos_articulos" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "nombre" varchar(30) NOT NULL, "categoria" varchar(20) NOT NULL, "precio" integer NOT NULL);
--
-- Create model Clientes
--
CREATE TABLE "gestionPedidos_clientes" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "nombre" varchar(30) NOT NULL, "direccion" varchar(50) NOT NULL, "email" varchar(254) NOT NULL, "telefono" varchar(9) NOT NULL);
--
-- Create model Pedidos
--
CREATE TABLE "gestionPedidos_pedidos" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "fecha" date NOT NULL, "entregado" bool NOT NULL);
COMMIT;

 Ahora, como último paso le decimos que las aplique, es decir ejecutamos la migración, esto si es obligatorio porque sino no se aplicarán los cambios:

/tiendaVirtual$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, gestionPedidos, 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 gestionPedidos.0001_initial... OK
  Applying sessions.0001_initial... OK
Si abres la tabla verás que tiene 14. La mayor parte las utiliza Django para su uso pero también están las nuestras:

tablas creadas en el archivo de la base de datos


Si te fijas Django añade por defecto un campo id que se añade como clave primaria, en caso de que tu no lo hagas, que también podrías.


¿Cómo crear, actualizar y borrar registros de la base de datos?


Para comenzar vamos a hacerlo desde la consola, aunque el objetivo final será hacerlo desde formularios que creemos en la página web. Pero hasta que no veamos como hacer formularios en Django, tendremos que hacerlo desde la consola.

Para ello abriremos el "shell" de Django dentro de nuestra aplicación (tiendaVirtual) de la siguiente forma:

~/Cursos/DJANGO/tiendaVirtual$ python manage.py shell
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 

Lo primero que vamos a hacer es importar el modelo con el que vamos a trabajar. Por ejemplo vamos a crear un registro de la tabla Artículos. Comenzamos importando el modelo.


~/Cursos/DJANGO/tiendaVirtual$ python manage.py shell
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from gestionPedidos.models import Articulos
Vamos a insertar un primer Articulo dentro de la tabla artículos. Creamos una variable que la podemos llamar como queramos, yo la llamaré "juego" y luego asignaremos cada uno de los campos, teniendo en cuenta si la propiedad es de tipo texto, entero etc. Por ejempo insertaremos en nuestra tienda virtual un primer videojuego:

"Doom", "Acción", 3 €

~/Cursos/DJANGO/tiendaVirtual$ python manage.py shell
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from gestionPedidos.models import Articulos
>>> juego=Articulos(nombre="Doom", categoria="Acción", precio= 3)
Para que esto tenga efecto y se cree el registro utilizamos el método .save() sobre la variable creada.

~/Cursos/DJANGO/tiendaVirtual$ python manage.py shell
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from gestionPedidos.models import Articulos
>>> juego=Articulos(nombre="Doom", categoria="Acción", precio= 3)
>>> juego.save()

y ya tenemos el registro creado.

imagen de registro creado en la base de datos


Para practicar vamos a insertar un segundo artículo.

>>> juego2=Articulos(nombre="Need for Speed", categoria="Velocidad", precio=50)
>>> juego2.save()
>>> 
Nuevo registro creado en la base de datos

Existe otra forma de insertar un registro con una sola instrucción que es usando el método "objects.create". 

El administrador predeterminado para cada modelo es objects. Este administrador recupera todos los objetos en la base de datos, aunque también podemos crear gestores de modelos personalizados (aunque no los vamos a ver en este curso).

Creemos un tercer articulo para verlo.

>>> juego3=Articulos.objects.create(nombre="Animal Crossing",categoria="Simulación", precio=45)
tercer articulo creado con una sola instrucción


Actualizar un registro.

Imaginemos que queremos modificar el precio del juego "Need for Speed" para subirlo a 60 Euros. Para realizar esta tarea, como use la variable "juego2" para crear el objeto, modificamos el precio de la siguiente forma:

>>> juego2.precio=60
>>> juego2.save()
>>>
y si vamos a la base de datos y actualizamos ya estaría modificado el precio.

Borrar registro.

Por ejemplo vamos a borrar el juego "Animal Crossing" que yo cree usando la variable "juego3". Podemos usar de nuevo esta variable u otra nueva (da igual el nombre de la variable) por ejemplo "borrar". Le especificamos el modelo (Articulos) y usamos objets.get para especificar el criterio. Podemos especificar el id, el nombre etc del registro. Yo usare el id del registro que en mi caso es el 3. Y una vez tenemos el registro seleccionado lo borramos usando el método "delete()"

>>> borrar = Articulos.objects.get(id=3)
>>> borrar.delete()
(1, {'gestionPedidos.Articulos': 1})
>>> 

resultado de borrar el registro numero 3


Para realizar una consulta que nos muestre todos los registros que tenemos almacenados en la tabla podemos usar le método .all()


>>> lista_articulos = Articulos.objects.all()
>>> lista_articulos
<QuerySet [<Articulos: Articulos object (1)>, <Articulos: Articulos object (2)>]>
>>> 
Si tienes curiosidad de ver la instrucción SQL que genera lo anterior solo tienes que ejecutar lo siguiente para verla:

>>> lista_articulos.query.__str__()
'SELECT "gestionPedidos_articulos"."id", "gestionPedidos_articulos"."nombre", "gestionPedidos_articulos"."categoria", "gestionPedidos_articulos"."precio" FROM "gestionPedidos_articulos"'
>>> 



No hay comentarios:

Publicar un comentario