Files
django-core-base/CLAUDE.md
juanjo 99de5f06b5
All checks were successful
DEPLOY_MULTI_BRACH/pipeline/head This commit looks good
docs: corregir flujo de ramas en CLAUDE.md (pre-dev → dev → master)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 01:15:04 +02:00

4.2 KiB

Convenciones del Ecosistema V-Encore Lab

Ecosistema de microservicios

Repo Rol Puerto
django-core-base Hub orquestador principal 8000
api_backoffice Consulta y gestión de BD 8001
api_comunicaciones Emails, notificaciones, webhooks 8002
api_documentacion Generación y gestión de documentos 8003
web_interno Panel de gestión (React + Ant Design) 3000

Stack Django

  • Django 5.0 + DRF + SimpleJWT
  • Apps bajo app/. Prefijo /api/ en todas las URLs salvo admin/.
  • Patrón 3 capas: URL → View → Action
  • SQL con connection.cursor() y placeholders (%s). Nunca concatenar strings.

Patrón de vistas — 4 bloques obligatorios

from general.utilidades.acciones import LogService

class MiVista(APIView):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def post(self, request):
        path = '/mi-app/mi-endpoint/'

        # Bloque 1 — Inicio Log
        log_id = LogService.gestionar_log(self, request, path=path)

        try:
            # Bloque 2 — Data Cleaning
            data = request.data
            LogService.gestionar_log(self, request, log_id=log_id,
                                     path=path, body_request=data, status_code=100)
            params = {'campo': data.get('campo')}
        except Exception as error:
            response = {'error': str(error)}
            LogService.gestionar_log(self, request, log_id=log_id,
                                     path=path, body_response=response, status_code=400)
            return JsonResponse(response, status=400)

        try:
            # Bloque 3 — Action Call
            resultado = mi_accion(params)
            # Bloque 4 — Cierre Log
            LogService.gestionar_log(self, request, log_id=log_id,
                                     path=path, body_response=resultado, status_code=200)
            return JsonResponse(resultado, status=200)
        except Exception as error:
            response = {'error': str(error)}
            LogService.gestionar_log(self, request, log_id=log_id,
                                     path=path, body_response=response, status_code=500)
            return JsonResponse(response, status=500)

LogService — reglas

  • Siempre llamar como LogService.gestionar_log(self, request, ...) — pasar self de la vista.
  • Primera llamada (sin log_id): crea el registro, devuelve el log_id.
  • Llamadas siguientes: actualizar con log_id=log_id.
  • body_request y body_response se serializan con DjangoJSONEncoder — soporta datetime.date, Decimal, etc.
  • status_code como entero. Usar is not None para comprobar (0 es válido).

Base de datos

  • DB_HOST definido → PostgreSQL
  • DB_HOST no definido → SQLite en app/data/db.sqlite3
  • Migraciones siempre desde app/: cd app && python manage.py migrate
  • SQL INSERT con psycopg2: usar INSERT ... RETURNING id + cursor.fetchone(). Nunca cursor.lastrowid.
  • Booleans en psycopg2: pasar True/False, no 1/0.

Flujo de ramas

pre-dev  →  dev  →  master
  • pre-dev: desarrollo activo — aquí entran todos los cambios
  • dev: validación previa a producción
  • master: producción estable
  • Merges siempre con --no-ff
  • NUNCA propagar en sentido inverso (master → dev o dev → pre-dev)
  • Secuencia correcta:
    git checkout pre-dev && git merge <mi-cambio> --no-ff
    git checkout dev     && git merge pre-dev --no-ff && git push origin dev
    git checkout master  && git merge dev --no-ff     && git push origin master
    

Estructura de app Django

app/
├── api_config/       # settings.py, urls.py, wsgi.py
├── general/          # LogService, utils — NO tiene modelos propios
├── backend_admin/    # Modelo Log (audit_logs), admin panel
├── common/           # Modelos y utilidades compartidas entre apps
├── <feature_app>/    # Una app por dominio de negocio
├── data/             # SQLite (gitignored, solo .gitkeep versionado)
└── manage.py

Fixtures

  • loaddata ignora auto_now_add=True — incluir fechas explícitas en el JSON o falla con NOT NULL en PostgreSQL.