Django models: Una aplicación
Ahora vamos a aplicar lo que hemos aprendido, dejando la teórica, ahora vamos a la práctica.
Para ello, crearemos una galería de productos.
Setup
Realizamos los pasos que ya hemos visto en lo que va de la asignatura...
- Creamos un entorno virtual de Python.
- Activamos el entorno virtual de Python.
- Instalamos Django.
- Creamos un proyecto Django.
- Realizamos la configuración básica de Django.
- Configuración del proyecto.
- Configuración de templates.
- Configuración de static.
- Configuración de i18n.
- Creamos una aplicación en nuestro proyecto Django. (tienda)
- Registramos nuestra aplicación en el proyecto.
- Creamos una vista de inicio para nuestra aplicación.
- Configuramos las urls de nuestra aplicación.
Creación del modelo
Ahora, creamos nuestro modelo dentro de ProyectoDjango/tienda/models.py
:
| class Producto(models.Model):
slug = models.SlugField()
nombre = models.CharField(max_length=100)
descripcion = models.TextField()
stock = models.PositiveSmallIntegerField()
precio = models.PositiveSmallIntegerField()
modificacion = models.DateTimeField(auto_now=True, auto_now_add=False)
creacion = models.DateTimeField(auto_now=False, auto_now_add=True)
def __str__(self):
return str("[{}] {} {}".format(self.slug, self.nombre, self.stock))
|
Migramos
La migración es un proceso automático que crea las tablas de nuestros modelos, o modificaciones que hayamos realizado a nuestros modelos ya creados.
Para ello, la aplicación debe estar registrada en settings.py
de nuestro proyecto.
Para realizar la migración, en la consola:
py manage.py makemigrations
Luego, migramos:
Si abrimos nuestro archivo db.sqlite3
con DB Browser, podremos observar que se han creado todas las tablas necesarias, incluyendo nuestra tabla Producto (tienda_producto
).
Shell de manage.py
Para la agregar datos, modificar, listar y eliminar datos, podemos usar la shell de manage.py
. Esto se logra mediante el comando:
Deberíamos ver que la consola tiene el estado:
| Python 3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
|
El >>>
nos dice que está listo para recibir código Python.
Para agregar productos, primero debemos importar el model
.
Nótese que la ubicación del script es en el directorio en donde manage.py
se encuentra.
Entonces, importamos nuestro modelo, teniendo en cuenta el nombre de la aplicación en la que se encuentra:
| from tienda.models import Producto
|
Una vez ya importado, podemos comenzar a crear registros, mediante bulk_create()
podemos insertar más de un registro a la vez:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | Producto.objects.bulk_create(
[
Producto(
slug="filorte",
nombre="Un pico de este porte",
descripcion="Muy grande",
stock=4,
precio=15000,
),
Producto(
slug="martillo-de-cristal",
nombre="Martillo de cristal",
descripcion="Martillo de cristal de 3 golpes",
stock=8,
precio=12000,
),
Producto(slug="pila-de-corriente-alterna",
nombre="Bateria AC",
descripcion="Bateria tipo pila de 12V AC",
stock=19,
precio=2790
),
]
)
|
No hace falta usar la función save()
. Ya que es instantáneo. Por lo que, debes revisar bien tus comandos.
Vistas para nuestra galería
La idea es generar una vista en donde se muestren todos los productos. Y otra vista para ver un producto en específico.
Entonces, manos a la obra!
Creación de la vista galería general
Primero creamos la vista de galería de productos.
En tienda/views.py
importamos nuestro modelo:
| from .models import Producto
|
Nótese que el .
en .models
es para referenciar el módulo actual, ósea, nuestra aplicación actual.
También es válido (y recomendable) usar from tienda.models import Producto
.
Pero es para que sepas que, si es relativo a sí mismo, podemos omitir el nombre.
Ahora, escribimos la vista:
| def index(request):
# 👇 variable 👇 devuelve todos los productos
productos = Producto.objects.all()
# 👇 llave - 👇 valor
return render(request, "tienda/index.html", {"productos": productos})
|
Definición de las templates
Creamos nuestro template base.html
dentro de templates/
:
Y ahora generamos el archivo index.html
dentro de templates/tienda/
:
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 | {% extends 'base.html' %}
{% block title %}Tienda{% endblock %}
{% block content %}
<div class="container">
<!-- primero verificamos que en nuetro contexto exista la llave 'productos' -->
{% if productos %}
<div class="row">
<!-- usamos un ciclo For de Python de toda la vida -->
{% for producto in productos %}
<div class="col-md-3">
<div class="card" style="width: 18rem;">
<!-- mostramos las variables mediante el uso de dobe llaves, que es para evaluar una variable -->
<div class="card-body">
<h5 class="card-title">{{ producto.nombre }}</h5>
<p class="card-text">
{{ producto.descripcion }}
<br>
<strong>Stock</strong> {{ producto.stock }}
<br>
<strong>Precio Unitario</strong> $ {{ producto.precio }}
<br>
</p>
</div>
</div>
</div>
<!-- siempre tenemos que terminar los tags -->
{% endfor %}
</div>
{% endif %}
</div>
{% endblock %}
|
Y listo, tenemos la galería de productos completa.
Creación de la vista para productos específicos
Ahora, para ver un producto en específico, sabemos que tenemos que hacer tres cosas:
- Crear la vista.
- Crear la ruta.
- Modificar el template
Creando la vista
En el mismísimo hogar/views.py
, creamos una nueva vista:
| # 👇 recibimos un parametro uid (el slug del Producto)
def producto(request, uid):
# 👇 buscamos el producto cuyo slug sea el que se nos ha dado
producto = Producto.objects.get(slug=uid)
# 👇 singular (solo es un producto)
return render(request, "tienda/index.html", {"producto":producto})
# notese que si le ponemos productos (con s final) tendremos problemas para modificar la template
|
Nótese que la función producto
recibe uid
, esto se debe definir en la ruta.
Creando la ruta
Tenemos que definir que una vista puede recibir parámetros a través de la URL. Para ello vamos a hogar/urls.py
y definimos una nueva ruta:
| urlpatterns = [
...
# 👇 tipo de dato 👇 vista (funcion que la recibe)
path('<slug:uid>/', app.producto, name="producto"),
# 👆 nombre de la variable 👆 para usar el tag 'url'
]
|
Ahora que la definimos, debemos hacer una modificación a la template templates/hogar/index.html
.
Modificando la template
Modificamos la template templates/hogar/index.html
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 | {% block content %}
<div class="container">
<!-- vemos si son todos los productos -->
{% if productos %}
<div class="row">
{% for producto in productos %}
<div class="col-md-3">
<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">{{ producto.nombre }}</h5>
<p class="card-text">
{{ producto.descripcion }}
<br>
<strong>Stock</strong> {{ producto.stock }}
<br>
<strong>Precio Unitario</strong> $ {{ producto.precio }}
<br>
<!-- un link para ir al la vista de ese producto -->
<a class="btn btn-primary" href="{% url 'tienda:producto' producto.slug %}">Ver</a>
<!-- nombre de la vista | argumento (uid) -->
<!--
USAMOS EL TAG url
que acepta el parametro uid que definimos como un argumento.
-->
</p>
</div>
</div>
</div>
{% endfor %}
</div>
<!-- si no son todos los productos, entoces vemos si es un producto -->
{% elif producto %}
<h2>{{ producto.nombre }}</h2>
<h4>{{ producto.descripcion }}</h4>
<br>
<div class="row text-center">
<div class="col-md-2">
<h5>Cantidad</h5>
{{ producto.stock }}
</div>
<div class="col-md-2">
<h5>Precio Unitario</h5>
{{ producto.precio }}
</div>
</div>
{% endif %}
</div>
{% endblock %}
|
Y listo. Ahora tenemos la galería general para todos los productos y una vista para un producto en específico.
TEST TIME
Cuando vas a la URL http://127.0.0.1:8000/ se debería ver así:
Y, si vas a la url http://127.0.0.1:8000/martillo-de-cristal/ deberias ver algo asi:
Si se puede usar la id
(<int:uid>
) del producto. Pero no queda "lindo", es un numero vacío, en cambio el slug
provee información clara de lo que estas solicitando.
Ya tiene lo básico. Ahora vas a sufrir.