Dentro de este cuarto y último tutorial se cubrirán los siguientes puntos:
Procesar nuevo pedido.
Mostrar histórico de pedidos.
Filtrar productos por categoría.
1. Procesar un nuevo pedido
- Dentro del paquete "models" de la aplicación
store
, crea un archivo Python: "pedido.py" y agrega la siguiente definición para el modelo:
...
...
from store.models import Pedido
from django.db import models
from django.contrib.auth.models import User
from .producto import Producto
class Pedido(models.Model):
usuario = models.ForeignKey(User, on_delete=models.CASCADE)
producto = models.ForeignKey(Producto, on_delete=models.CASCADE)
cantidad = models.PositiveIntegerField(default=1)
total = models.DecimalField(max_digits=12, decimal_places=2)
fecha_registro = models.DateTimeField(auto_now_add=True)
fecha_ult_act = models.DateTimeField(auto_now=True)
def __str__(self) -> str:
return f'{self.id}'
class Meta:
db_table = 'st_pedidos'
verbose_name = 'Pedido'
verbose_name_plural = 'Pedidos'`
El modelo Pedido se utilizará para registrar los nuevos pedidos.
Dado que hemos creado un nuevo modelo debemos crear y aplicar la migración respetiva para reflejarlo en la base de datos, usando los comandos:
poetry run python manage.py makemigrations
, y
poetry run python manage.py migrate
- A continuación, debemos crear la "URL" a través de la cual se procesará el registro de cada pedido. Agrega el siguiente código a tu archivo urls.py de la aplicación
store
:
urlpatterns = [
# Otras rutas
path('pedidos/', views.crear_pedido, name='crear_pedido')
]
- Una vez que la ruta esté creada vamos a asociarla con su función de vista correspondiente, para ello crearemos la función
crear_pedido
en el archivo views.py de la aplicaciónstore
:
def crear_pedido(request):
try:
datos_pedido = json.loads(request.body)
producto_id = int(datos_pedido.get('producto_id'))
cantidad = int(datos_pedido.get('cantidad'))
producto = Producto.objects.get(pk=producto_id)
nuevo_pedido = Pedido( usuario=request.user,
producto=producto,
cantidad=cantidad,
total=cantidad*producto.precio)
nuevo_pedido.save()
return JsonResponse({'success': True, 'message': f'Se registró el pedido exitosamente. Pedido # {nuevo_pedido.id}'}, status=200)
except Exception as ex:
return JsonResponse({'success': False, 'message': str(ex)}, status=500)
- Posteriormente realizaremos la petición http vía ajax que se encargará de consumir la ruta de creación de pedido al momento que el usuario desee ingresar un nuevo pedido. Para ello, vamos a crear un nuevo archivo estático de javascript dentro de la carpeta
static/js
, el archivo podría llamarsepedido.js
.
Dentro del archivo, procedemos a registrar la siguiente función:
function crearPedido(producto_id, csrf_token){
const jsonData= {
producto_id: producto_id,
cantidad: 1
}
axios.post('/pedidos/', jsonData, {
headers: {
'X-CSRFToken': csrfToken
}
})
.then(response => {
alert(response.data.message);
})
.catch(error => {
if (error.response) {
alert(error.response.data.message);
}else {
alert(error.message);
}
});
}
- Finalmente, vamos a conectar todo desde la plantilla "catalog.html", aquí haremos que se ejecute la función
crearPedido
que recién creamos. En el botón "Hacer Pedido" vamos a manejar el evento onclick ejecutando el llamado de la funcióncrearPedido
de la siguiente manera:
onclick="crearPedido('{{producto.id}}', '{{csrf_token}}')"
Para que funcione debemos registrar el archivo de javascript pedido.js
dentro de la plantilla:
<script src="{% static 'js/pedido.js' %}"></script>
Procedemos a ejecutar todo validando que se creen los nuevos pedidos.
2. Mostrar histórico de pedidos del usuario
Ahora vamos a editar la función de vista get_mis_pedidos
para consultar los pedidos del usuario y mostrarlos.
Editemos la función de vista de la siguiente manera:
def get_mis_pedidos(request):
pedidos = Pedido.objects.filter(usuario=request.user).order_by('-id')
return render(request, 'mis-pedidos.html', {'pedidos': pedidos})
Y editemos la plantilla "mis-pedidos.html" para mostrar los pedidos del usuario en una tabla:
<div class="mt-5 table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Pedido</th>
<th scope="col">Producto</th>
<th scope="col">Cantidad</th>
<th scope="col">Total</th>
<th scope="col">Fecha Reg.</th>
<th></th>
</tr>
</thead>
<tbody>
{% for pedido in pedidos %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ pedido.id }}</td>
<td>{{ pedido.producto.nombre }}</td>
<td>{{ pedido.cantidad }}</td>
<td>{{ pedido.total }}</td>
<td>{{ pedido.fecha_registro }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
3. Permitir el filtro de productos por categoría
Como último punto vamos a habilitar el filtro de productos por categoría, para ello necesitamos crear un procesador de contexto (context_processor).
Un context_processor en Django es una función que toma una solicitud y devuelve un diccionario de datos que se añade automáticamente al contexto de todas las plantillas renderizadas, permitiendo que ciertos datos estén disponibles globalmente sin tener que pasarlos explícitamente en cada vista.
Primero debemos crear el archivo context_processors.py dentro del directorio de la aplicación "store". Una vez creado procedemos a ingresar a crear el context_processor para consultar todas las categorías:
from store.models import Categoria
def get_all_categorias(request):
categorias = Categoria.objects.all()
return {'categorias': categorias}
A continuación, debemos registrar el context_processor en la configuración del proyecto. Nos vamos a ecommerce/settings.py
y dentro del archivo vamos a ubicar la sección de TEMPLATES, en esta sección ubicamos los context_processors y agregamos el nuestro de la siguiente manera:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
...
'store.context_processors.get_all_categorias'
],
},
},
]
Luego debemos ir a la plantilla "index.html" para hacer que se rendericen todas las categorías como una opción de submenú dentro del select de categorías, de la siguiente manera:
{% for categoria in categorias %}
<li><a class="dropdown-item" href="{% url 'productos_por_categoria' categoria_id=categoria.id %}"> {{categoria.nombre}} </a></li>
{% endfor %}
Finalmente crear una nueva URL y función de vista dentro de la aplicación store
que permitan consultar y mostrar los productos filtrados por categoría.
La función de vista podría quedar así:
def get_productos_por_categoria(request, categoria_id):
productos = Producto.objects.filter(categorias__in=[categoria_id])
return render(request, 'catalog.html', {'productos': productos})
y la nueva URL así:
urlpatterns = [
# Otras rutas
path('categorias/<int:categoria_id>/productos/', views.get_productos_por_categoria, name='productos_por_categoria'),
]
Probemos que funcione y nuestro proyecto estaría completo.
Top comments (0)