Creación de Modelos
Los modelos hacen referencia a las tablas del diseño de su base de datos. Para este caso asumimos el siguiente diseño.
Antes de crear los modelos de la aplicación es necesario que configuremos nuestra base de datos.
Especificación de la base de datos
Primero se debe instalar las extensiones en Django que permiten comunicarse con el motor de la base de datos.
Para este caso utilizaremos MySql
, por lo cual instalamos:
mysqlclient
python3 -m pip install mysqlclient
En caso que se genere algun error probar con la instalación de la siguiente manera:
Y luego intentar nuevamente
python3 -m pip install mysqlclient
Éste es también el punto donde normalmente especificarías la base de datos a utilizar en el proyecto --- tiene sentido usar la misma base datos para desarrollo y producción donde sea posible, para evitar diferencias menores en el comportamiento. Puedes encontrar información sobre las diferentes opciones de bases de datos en Databases (Django docs).
sitealmacen/sitealmacen/settings.py - Actualizar con el siguiente código.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'almacen2022_mysql',
'USER': 'root',
'PASSWORD': 'MiNiCo57**',
'HOST': 'localhost',
'PORT': '3306'
}
}
Esto nos indica que procedemos a varios procesos.
-
Instalar el motor de la base de datos que para este caso es MySql.
https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-database
-
Una vez instalado el motor debemos iniciar dicho motor.
Abrimos la terminal de Ubuntu WSL y escribimos.
sudo /etc/init.d/mysql start
Si aparece este mensaje, quiere decir que ya esta inicializado.
* Starting MySQL database server mysqld
-
Crear la base de datos indicada:
'NAME': 'almacen2022_mysql',
para ello, en la terminal de Ubuntu WSL ingresarsudo mysql -u root -p
Y luego la contraseña.
Si aparece en la terminal
mysql> Indica que ya entró al motor de MySQL.
Luego realice:
show databases;
Para mostrar las bases de datos que tiene creadascreate database almacen2022_mysql;
Debe aparecer en pantalla, para indicar que ha sido creada.
Query OK, 1 row affected (0.01 sec)
Ya podemos probar realizando las migraciones, sin aun haber realizado los modelos. Esto es debido a que Django ya trae unos modelos pre establecidos.
Para ello, migramos de la siguiente manera:
En la ventana de terminal del proyecto en Visual Studio Code, recordemos que debe estar activa la unidad virtual y ubicados en la carpeta del proyecto sitealmacen
. tal como se muestra.
(.venv) ubuntu@PortatlJQ:~/appsweb/clasesdlloweb/backdjango/2022iisem/sitealmacen$
Escribimos lo siguiente:
python3 manage.py makemigrations
=> Crea las migraciones
python3 manage.py migrate
==> Crea la base de datos físicamente, de acuerdo a las migraciones actuales.
Podemos probar en la terminar de Ubuntu, con el motor de MySQL abierto, para que nos muestre las tablas generadas en la base de datos que fueron creadas automáticamente, con la siguiente instrucción:
use almacen2022_mysql;
==> Para entrar a la base de datos
show tables; ==> Para mostrar las tablas de la base de datos.
Dando como resultado:
+-----------------------------+
| Tables_in_almacen2022_mysql |
+-----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+-----------------------------+
10 rows in set (0.00 sec)
Código de los Modelos
Aplicación Clientes
Los códigos de los modelos se realizan dentro de cada aplicación, que para este caso en particular se crearían en Apps/clientes/models.py
de la siguiente manera:
En este caso tomaremos la tabla de clientes dentro de la aplicación correspondiente
Modelo de Cliente
from django.db import models
# Create your models here.
class Cliente(models.Model):
nombreCliente = models.CharField(max_length=100, help_text="Ingrese el Nombre del Cliente")
direccionCliente = models.CharField(max_length=100, help_text="Ingrese la Direccion del Cliente")
telefonoCliente = models.CharField(max_length=12, help_text="Ingrese el Telefono del Cliente")
correoCliente = models.EmailField(max_length=100, help_text="Ingrese el Correo del Cliente")
passwordCliente = models.CharField(max_length=100, help_text="Ingrese el Password del Cliente")
def __str__(self):
return self.nombreCliente
class Meta:
verbose_name = "cliente"
verbose_name_plural = "clientes"
Cada modelo obedece a una clase que hereda o extiende de la clase models.Model
, la cual debemos importar.
Cada campo o atributo del modelo, para este caso Cliente posee Nombre, Tipo y Argumento de los campos.
Tipo de los Campos
El tipo del campo pueden ser (Numérico, Fecha, Boolean, entre otros). Para saber todos los tipos de los campos: TIPOS DE CAMPOS
Los siguientes tipos de campos comunes:
NOMBRE DEL CAMPO | DESCRIPCIÓN |
---|---|
AutoField | Es un IntegerField que se incrementa automáticamente. |
BigAutoField | Es un entero de 64 bits, muy parecido a un AutoField, excepto que se garantiza que se ajusta a los números del 1 al 9223372036854775807. |
BigIntegerField | Es un número entero de 64 bits, muy parecido a un IntegerField, excepto que se garantiza que se ajusta a números de -9223372036854775808 a 9223372036854775807. |
BinaryField | Un campo para almacenar datos binarios sin procesar. |
BooleanField | Un campo verdadero / falso. El widget de formulario predeterminado para este campo es CheckboxInput. |
CharField | Es una fecha, representada en Python por una instancia de datetime.date. |
DateField | Una fecha, representada en Python por una instancia de datetime.date |
Se utiliza para la fecha y la hora, representada en Python por una instancia de datetime.datetime. | |
DecimalField | Es un número decimal de precisión fija, representado en Python por una instancia Decimal. |
DurationField | Un campo para almacenar períodos de tiempo. |
EmailField | Es un CharField que verifica que el valor sea una dirección de correo electrónico válida. |
FileField | Es un campo de carga de archivos. |
FloatField | Es un número de punto flotante representado en Python por una instancia flotante. |
ImageField | Hereda todos los atributos y métodos de FileField, pero también valida que el objeto cargado es una imagen válida. |
IntegerField | Es un campo entero. Los valores de -2147483648 a 2147483647 están seguros en todas las bases de datos compatibles con Django. |
GenericIPAddressField | Una dirección IPv4 o IPv6, en formato de cadena(por ejemplo, 192.0.2.30 o 2a02: 42fe :: 4). |
NullBooleanField | Como BooleanField, pero permite NULL como una de las opciones. |
PositiveIntegerField | Como un IntegerField, pero debe ser positivo o cero(0). |
PositivoSmallIntegerField | Como PositiveIntegerField, pero solo permite valores bajo un cierto punto(dependiente de la base de datos). |
SlugField | Slug es un término periodístico. Una slug es una etiqueta corta para algo, que contiene solo letras, números, guiones bajos o guiones. Generalmente se utilizan en URL. |
SmallIntegerField | Es como un IntegerField, pero solo permite valores bajo un cierto punto(dependiente de la base de datos). |
TextField | Un campo de texto grande. El widget de formulario predeterminado para este campo es un área de texto. |
TimeField | Una hora, representada en Python por una instancia de datetime.time. |
URLField | Un CharField para una URL, validado por URLValidator. |
UUIDField | Un campo para almacenar identificadores únicos universales. Utiliza la clase UUID de Python. Cuando se usa en PostgreSQL, esto se almacena en un tipo de datos uuid, de lo contrario en un char(32). |
Argumento de los Campos
Los siguientes argumentos son comunes a la mayoría de los tipos de campo y pueden usarse al declararlos:
-
max_length=20
--- Establece que la longitud máxima del valor de este campo es 20 caracteres. -
help_text="Enter field documentation"
--- proporciona una etiqueta de texto para mostrar que ayuda a los usuarios a saber qué valor proporcionar cuando un usuario ha de introducirlo via un formulario HTML. -
help_text: Proporciona una etiqueta de texto para formularios HTML (ej. en el sitio de Administración), tal como se describe arriba.
-
verbose_name: Nombre de fácil lectura que se usa en etiquetas para el campo. Si no se especifica, Django inferirá el valor por defecto del verbose name a partir del nombre del campo.
-
default: Valor por defecto para el campo. Puede ser un valor o un callable object (objeto que puede ser llamado como una función), en cuyo caso el objeto será llamado cada vez que se cree un nuevo registro.
-
null: Si es
True
, Django guardará valores en blanco o vacíos comoNULL
en la base de datos para campos donde sea apropiado (unCharField
guardará una cadena vacía en su lugar). Por defecto esFalse
. -
blank: Si es
True
, se permite que el campo quede en blanco en tus formularios. El valor por defecto esFalse
, lo que significa que la validación de formularios de Django te forzará a introducir un valor. Con frecuencia se usa connull=True
, porque si vas a permitir valores en blanco, también querrás que la base de datos sea capaz de representarlos de forma apropiada. -
choices: Un grupo de valores de selección para este campo. Si se proporciona, el widget correspondiente por defecto del formulario será una caja de selección con estos valores de selección en vez del campo de texto estándar.
-
primary_key: Si es
True
, establece el campo actual como clave primaria para el modelo (Una clave primaria es una columna especial de la base de datos, diseñada para identificar de forma única todos los diferentes registros de una tabla). Si no se especifica ningún campo como clave primaria, Django añadirá automáticamente un campo para este propósito.
Métodos
Un modelo puede tener también métodos
Minimamente, en cada modelo deberías definir el método estándar de las clases de Python __str__()
para devolver una cadena de texto legible por humanos para cada objeto. Esta cadena se usa para representar registros individuales en el sitio de administración (y en cualquier otro lugar donde necesites referirte a una instancia del modelo). Con frecuencia éste devolverá un título o nombre de campo del modelo.
Recuerde que self.nombre
==> self
, indica que estamos en una función dentro de una clase, es decir un método y nombre
hace referencia a la propiedad o variable de la clase.
Metadatos
Puedes declarar metadatos a nivel de modelo para tu Modelo declarando class Meta
, tal como se muestra.
La forma en que aparecen los modelos en el admin que genera Django.
Una vez definido el modelo, procedemos a crear las migraciones y la generación física de la base de datos, ingresamos en la terminal de visual studio code. (Con el ambiente virtual activado)
Aplicación Productos
Los códigos de los modelos se realizan dentro de cada aplicación, que para este caso en particular se crearían en Apps/productos/models.py
de la siguiente manera:
Cuando se presentan varias tablas, primero se toma en consideración las tablas que no tienen llaves foráneas.
Modelo de tipoproductos y productos
from django.db import models
# Create your models here.
class TipoProducto(models.Model):
nombre = models.CharField(max_length=50, verbose_name="Nombre")
def __str__(self):
return self.nombre
class Meta:
verbose_name = "tipo producto"
verbose_name_plural = "tipo productos"
class Producto(models.Model):
nombre = models.CharField(max_length=50, verbose_name="Nombre")
marca = models.CharField(max_length=50, verbose_name="Marca")
precio = models.FloatField(verbose_name="Precio")
stockmin = models.IntegerField(verbose_name="Stock Minimo")
cantidad = models.IntegerField(verbose_name="Cantidad")
tipoproducto = models.ForeignKey(TipoProducto,
null=True,
blank=True,
on_delete=models.CASCADE)
def __str__(self):
return self.nombre
class Meta:
verbose_name = "producto"
verbose_name_plural = " productos"
Una vez definido el modelo, procedemos a crear las migraciones y la generación física de la base de datos, ingresamos en la terminal de visual studio code. (Con el ambiente virtual activado)
En este modelo se aprecia que relacionamos las tablas asociadas a las clases de TipoProducto
y Producto
, ambas se encuentran en el mismo archivo.
Como es una relación de uno a muchos, en donde se indica en la tabla de productos, evidenciando que pueden existir muchos tipos de productos en la tabla productos. Por lo que se concreta en:
tipoproducto = models.ForeignKey(TipoProducto,
null=True,
blank=True,
on_delete=models.CASCADE)
Aplicación Ventas
Los códigos de los modelos se realizan dentro de cada aplicación, que para este caso en particular se crearían en Apps/ventas/models.py
de la siguiente manera:
Cuando se presentan varias tablas, primero se toma en consideración las tablas que no tienen llaves foráneas.
Modelo de ventas y producto_ventas
from django.db import models
from django.utils.timezone import now
from django.contrib.auth.models import User
from Apps.clientes.models import Cliente
from Apps.productos.models import Producto
# Create your models here.
class Venta(models.Model):
fecha = models.DateField(default=now, verbose_name="Fecha Actual")
descuento = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="Descuento")
total = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Total")
subtotal = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Sub Total")
usuario= models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Usuario")
producto = models.ManyToManyField(Producto, through='VentaProducto', verbose_name="VentaProducto")
created = models.DateTimeField(auto_now=True, verbose_name="Fecha de Creacion")
updated = models.DateTimeField(auto_now=True, verbose_name="Fecha de Edicion")
cliente = models.ForeignKey(Cliente,
null=True,
blank=True,
on_delete=models.CASCADE)
class Meta:
verbose_name = "venta producto"
verbose_name_plural = "Ventas Productos"
class VentaProducto(models.Model):
producto = models.ForeignKey(Producto, on_delete=models.CASCADE, verbose_name="Producto")
venta = models.ForeignKey(Venta, on_delete=models.CASCADE, verbose_name="Venta")
fechaVenta = models.DateTimeField(auto_now=True, verbose_name="fecha")
precio = models.IntegerField(verbose_name="Precio")
cantidad = models.IntegerField(verbose_name="Cantidad")
total = models.FloatField(verbose_name="Total")
Una vez definido el modelo, procedemos a crear las migraciones y la generación física de la base de datos, ingresamos en la terminal de visual studio code. (Con el ambiente virtual activado)
En este modelo se aprecia que relacionamos las tablas asociadas a las clases de usuarios
y ventas
, estas clases se encuentran en diferentes archivos, por cuanto obliga a importar dicha clase.
from django.contrib.auth.models import User
y luego relacionamos
usuario= models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Usuario")
Como es una relación de uno a muchos, en donde se indica en la tabla de ventas, evidenciando que pueden existir muchos usuarioss en la tabla ventas.
También relacionamos las tablas asociadas a las clases de productos
y ventas
, estas clases se encuentran en diferentes archivos, por cuanto obliga a importar dicha clase.
from Apps.productos.models import Producto
Y luego relacionamos
producto = models.ManyToManyField(Producto, through='VentaProducto', verbose_name="VentaProducto")
Como es una relación de muchos a muchos, se procede a crear una nueva nueva tabla, que en este caso es un nueva clase denominada en el atributo through='VentaProducto
.
En esta nueva clase se pueden agregar campos adicionales que usted considere en esta nueva tabla.
class VentaProducto(models.Model):
producto = models.ForeignKey(Producto, on_delete=models.CASCADE, verbose_name="Producto")
venta = models.ForeignKey(Venta, on_delete=models.CASCADE, verbose_name="Venta")
fechaVenta = models.DateTimeField(auto_now=True, verbose_name="fecha")
precio = models.IntegerField(verbose_name="Precio")
cantidad = models.IntegerField(verbose_name="Cantidad")
total = models.FloatField(verbose_name="Total")