Desarrollo de Ecommerce con Django (parte 4)

Gabriel Villacis - Jul 15 - - Dev Community

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'`
Enter fullscreen mode Exit fullscreen mode

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')
]
Enter fullscreen mode Exit fullscreen mode
  • 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ón store:

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)

Enter fullscreen mode Exit fullscreen mode
  • 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 llamarse pedido.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);
        }
    });
}

Enter fullscreen mode Exit fullscreen mode
  • 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ón crearPedido de la siguiente manera:
onclick="crearPedido('{{producto.id}}', '{{csrf_token}}')"
Enter fullscreen mode Exit fullscreen mode

Para que funcione debemos registrar el archivo de javascript pedido.js dentro de la plantilla:

<script src="{% static 'js/pedido.js' %}"></script> 
Enter fullscreen mode Exit fullscreen mode

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})

Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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}
Enter fullscreen mode Exit fullscreen mode

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'
            ],
        },
    },
]
Enter fullscreen mode Exit fullscreen mode

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 %}
Enter fullscreen mode Exit fullscreen mode

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})

Enter fullscreen mode Exit fullscreen mode

y la nueva URL así:

urlpatterns = [
  # Otras rutas
  path('categorias/<int:categoria_id>/productos/', views.get_productos_por_categoria, name='productos_por_categoria'),
]
Enter fullscreen mode Exit fullscreen mode

Probemos que funcione y nuestro proyecto estaría completo.

. . . . . . . . . . . . . .
Terabox Video Player