Fase 3. Desarrollo de la Aplicación

En esta fase, vamos a estructurar cómo se desarrollarán los distintos módulos del sistema, tanto en el backend como en el frontend, para implementar las funcionalidades esenciales del proyecto.

1. Desarrollo del Backend (Django con Django REST Framework)

A. Configuración Inicial del Proyecto

1 Instalación de Dependencias: Instalaremos las dependencias necesarias en el entorno virtual de Python.

pip install django djangorestframework psycopg2-binary django-environ djangorestframework-jwt redis
  1. Configuración del Proyecto Django:

    • Crear el proyecto Django con el comando:
django-admin startproject backend .
  • Crear las aplicaciones para autenticación, productos y pedidos:
python manage.py startapp auth
python manage.py startapp products
python manage.py startapp orders
  • Configuración de la Base de Datos:
  1. En el archivo settings.py, configura la conexión a PostgreSQL utilizando el paquete django-environ para gestionar variables de entorno. Asegúrate de tener un archivo .env con las credenciales necesarias:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST'),
        'PORT': os.environ.get('DB_PORT', 5432),
    }
}

Y en el archivo .env, agrega las variables de entorno:

DB_NAME=mydatabase
DB_USER=myuser
DB_PASSWORD=mypassword
DB_HOST=localhost
DB_PORT=5432

B. Implementación de Modelos

  1. Modelo de Usuario:

    • En el archivo auth/models.py, crea un modelo de usuario si decides personalizarlo (si no, puedes usar el modelo User por defecto de Django).
  2. Modelo de Producto:

    • En products/models.py, define el modelo para los productos con campos como nombre, precio, inventario, imagen, etc.
class Producto(models.Model):
    nombre = models.CharField(max_length=255)
    precio = models.DecimalField(max_digits=10, decimal_places=2)
    descripcion = models.TextField()
    inventario = models.IntegerField()
    imagen = models.ImageField(upload_to='productos/')
  1. Modelo de Pedido:

En orders/models.py, crea un modelo para los pedidos, con campos como usuario, productos, fecha, estado, etc.

class Pedido(models.Model):
    usuario = models.ForeignKey(User, on_delete=models.CASCADE)
    productos = models.ManyToManyField(Producto)
    fecha = models.DateTimeField(auto_now_add=True)
    estado = models.CharField(max_length=50)
    total = models.DecimalField(max_digits=10, decimal_places=2)

C. Serializadores

En el backend, usarás serializers para transformar los datos entre los modelos y las respuestas JSON:

  1. Serializador de Producto (en products/serializers.py):
from rest_framework import serializers
from .models import Producto

class ProductoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Producto
        fields = ['id', 'nombre', 'precio', 'descripcion', 'inventario', 'imagen']
  1. Serializador de Pedido (en orders/serializers.py):
from rest_framework import serializers
from .models import Pedido
from products.serializers import ProductoSerializer

class PedidoSerializer(serializers.ModelSerializer):
    productos = ProductoSerializer(many=True)

    class Meta:
        model = Pedido
        fields = ['id', 'usuario', 'productos', 'fecha', 'estado', 'total']

D. Vistas y Rutas

  1. Vistas para el Producto (en products/views.py):
from rest_framework import viewsets
from .models import Producto
from .serializers import ProductoSerializer

class ProductoViewSet(viewsets.ModelViewSet):
    queryset = Producto.objects.all()
    serializer_class = ProductoSerializer
  1. Vistas para el Pedido (en orders/views.py):
from rest_framework import viewsets
from .models import Pedido
from .serializers import PedidoSerializer

class PedidoViewSet(viewsets.ModelViewSet):
    queryset = Pedido.objects.all()
    serializer_class = PedidoSerializer
  1. Rutas (en urls.py):
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from products.views import ProductoViewSet
from orders.views import PedidoViewSet

router = DefaultRouter()
router.register(r'productos', ProductoViewSet)
router.register(r'pedidos', PedidoViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

E. Autenticación (JWT)

  1. Configuración de JWT:
  • Instala el paquete djangorestframework-jwt para la autenticación con JWT.
pip install djangorestframework-jwt
  • En settings.py, agrega la configuración para JWT:
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}
  1. Vistas de Login/Logout:
  • Crea vistas para manejar el login y logout de los usuarios, utilizando JWT.

2. Desarrollo del Frontend (React con Vite)

A. Configuración Inicial del Proyecto

  1. Crear el Proyecto React con Vite:
npm create vite@latest frontend --template react
cd frontend
npm install
  1. Instalar Dependencias:
npm install axios react-router-dom

B. Estructura de Archivos

En el frontend, la estructura del proyecto será la siguiente:

frontend/
├── src/
│   ├── components/
│   │   ├── Header.js
│   │   └── ProductList.js
│   ├── pages/
│   │   ├── HomePage.js
│   │   └── ProductPage.js
│   ├── services/
│   │   └── api.js
│   ├── App.js
│   ├── index.js
│   └── store/
├── public/
├── tailwind.config.js
├── vite.config.js
└── .env

C. Lógica de Peticiones con Axios

  1. Servicio API (en services/api.js):
import axios from 'axios';

const API_URL = 'http://localhost:8000/api/';

export const getProductos = async () => {
    const response = await axios.get(`${API_URL}productos/`);
    return response.data;
};

export const getPedido = async (id) => {
    const response = await axios.get(`${API_URL}pedidos/${id}/`);
    return response.data;
};
  1. Componente de Lista de Productos (en components/ProductList.js):
import React, { useEffect, useState } from 'react';
import { getProductos } from '../services/api';

const ProductList = () => {
    const [productos, setProductos] = useState([]);

    useEffect(() => {
        const fetchProductos = async () => {
            const data = await getProductos();
            setProductos(data);
        };

        fetchProductos();
    }, []);

    return (
        <div>
            <h2>Productos</h2>
            <ul>
                {productos.map((producto) => (
                    <li key={producto.id}>{producto.nombre}</li>
                ))}
            </ul>
        </div>
    );
};

export default ProductList;

3. Despliegue y Configuración de Docker

A. Configuración de Docker

  1. Dockerfile para el Backend:
# Dockerfile para Backend
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
  1. Dockerfile para el Frontend:
# Dockerfile para Frontend
FROM node:16

WORKDIR /app

COPY package.json .
COPY package-lock.json .

RUN npm install

COPY . .

CMD ["npm", "run", "dev"]
  1. docker-compose.yml:
services:
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    depends_on:
      - db

  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend

  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydatabase