Skip to content

openlabun/rutasVivasService

Repository files navigation

Documentación Técnica — Rutas Vivas Service (Backend)

Resumen general

Rutas Vivas Service es el backend desarrollado en Django para la app móvil RutasVivas. Provee los endpoints necesarios para:

  • Obtener hitos (landmarks) y estaciones (stations).
  • Generar rutas emocionales (emotional routes) según mood y tiempo.
  • Crear usuarios locales (UserLocal).
  • Crear comentarios sobre hitos (landmark comments).
  • Subir imágenes secundarias de hitos.
  • Cargar masiva de hitos y exportar hitos en formato GeoJSON.

El proyecto incluye además un portal administrativo (Django admin) para gestionar hitos, estaciones y comentarios.

Nota: el urls.py expone las rutas que se documentan a continuación. En entorno DEBUG el servidor sirve MEDIA_URL desde MEDIA_ROOT.


Convenciones generales de la API

  • Formato de intercambio: JSON para la mayoría de endpoints (excepto uploads multipart).
  • Encabezados recomendados:
    • Content-Type: application/json para JSON.
    • Content-Type: multipart/form-data para subida de archivos.
    • Accept: application/json
  • Códigos de respuesta comunes:
    • 200 OK — petición correcta (GET, PUT que devuelven recurso).
    • 201 Created — recurso creado (POST).
    • 204 No Content — operación exitosa sin cuerpo (DELETE o POST sin retorno).
    • 400 Bad Request — validación fallida.
    • 401 Unauthorized / 403 Forbidden — si se usa autenticación/permiso y falla.
    • 404 Not Found — recurso no existe.
    • 500 Internal Server Error — error servidor.

Endpoints

1) POST /api/emotional-route/

Nombre: EmotionalRouteView
Método: POST
Descripción: Genera una ruta emocional (secuencia de hitos y estaciones) según parámetros enviados por el cliente (mood, duración, posición inicial.). Se espera que la vista haga la lógica de selección y ordenamiento de hitos.

Request (application/json)ejemplo recomendado:

{
  "mood": "Neutro", // string: mood elegido (e.g., Neutro)
  "duration_minutes": 45, // integer: duración total estimada en minutos
  "start_location": {
    //lat/lng para punto de inicio.
    "lat": 11.000123,
    "lng": -74.850321
  }
}

Response 200 (application/json)ejemplo recomendado:

{
  "route_id": "route_20251012_001",
  "mood": "Neutro",
  "duration_minutes": 45,
  "estimated_distance_m": 3200,
  "start_point": { "lat": 11.000123, "lng": -74.850321 },
  "landmarks": [
    {
      "id": 12,
      "name": "Hito Principal",
      "description": "Descripción breve",
      "lat": 11.0005,
      "lng": -74.8509,
      "sequence": 1,
      "estimated_time_at_landmark_min": 5
    },
    {
      "id": 7,
      "name": "Plaza central",
      "lat": 11.0012,
      "lng": -74.851,
      "sequence": 2
    }
  ],
  "geojson": {
    /* opcional: GeoJSON FeatureCollection del trayecto */
  }
}

Errores comunes:

  • 400 si mood, duration_minutes o start_location faltan o son inválidos.
  • 500 si la generación falla por error interno.

Observaciones y recomendaciones:

  • Es preferible devolver también una representación GeoJSON del trayecto (FeatureCollection con LineString del path y Point para cada landmark) para que el cliente lo pinte directamente en el mapa.
  • Añadir route_id permite al backend guardar recorrido finalizado o reconsultarlo.

2) GET /api/landmarks.geojson/

Nombre: landmarks_geojson Método: GET Descripción: Devuelve todos los hitos como un GeoJSON FeatureCollection. Útil para cargar capas en flutter_map sin transformación adicional.

Query parameters (opcionales):

  • bbox — bounding box en formato minLng,minLat,maxLng,maxLat para filtrar por área.
  • mood — para filtrar hitos por mood categorizado.
  • limit, offset — paginación.

Response 200 (application/geo+json)ejemplo:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 12,
      "properties": {
        "name": "Hito Principal",
        "description": "Texto...",
        "category": "historia",
        "images": [
          "/media/landmarks/12/main.jpg",
          "/media/landmarks/12/secondary_1.jpg"
        ],
        "info_url": "/api/landmarks/12/"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-74.850900, 11.000500]
      }
    },
    ...
  ]
}

Errores comunes:

  • 400 si bbox malformado.
  • 500 por errores de serialización.

Observaciones:

  • Content-Type ideal: application/geo+json o application/json.
  • Para performance, soportar filtrado por bbox y paginación.

3) POST /api/landmarks/bulk/

Nombre: LandmarkBulkCreateView Método: POST Descripción: Endpoint para creación masiva de hitos (bulk). Se usa para importar datasets (CSV/JSON) desde herramientas administrativas o scripts de migración.

Request (application/json)ejemplo:

{
  "landmarks": [
    {
      "external_id": "L-001",
      "name": "Hito A",
      "description": "Descripción A",
      "lat": 11.0001,
      "lng": -74.8501,
      "category": "arte",
      "images": [],
      "meta": { "difficulty": "low" }
    },
    {
      "external_id": "L-002",
      "name": "Hito B",
      "lat": 11.0002,
      "lng": -74.8502
    }
  ],
  "validate_only": false // opcional: si true, valida sin persistir
}

Response 201 (application/json)ejemplo:

{
  "created": 2,
  "errors": []
}

Response 207 Multi-Status — si algunos elementos fallan; recomendable devolver array con resultados por elemento:

{
  "results": [
    { "external_id": "L-001", "status": 201, "id": 12 },
    {
      "external_id": "L-002",
      "status": 400,
      "errors": { "lat": ["Campo requerido"] }
    }
  ]
}

Errores comunes:

  • 400 si el body no contiene landmarks o está mal formado.
  • Validaciones por item devueltas en array.

Observaciones:

  • Implementar validación por item y transacciones parciales (configurable).
  • Aceptar también CSV mediante multipart/form-data con procesamiento server-side puede ser útil.

4) POST /landmarks/<int:landmark_id>/upload-image/

Nombre: LandmarkImageUploadView Método: POST Descripción: Subida de imagen secundaria (o primaria) para un hito. Endpoint dirigido a recibir archivos multimedia y asociarlos al landmark_id.

Request (multipart/form-data) — campos:

  • image (archivo) — requerido.
  • is_primary (boolean) — opcional.
  • alt (string) — texto alternativo.

Curl ejemplo:

curl -X POST "https://api.example.com/landmarks/12/upload-image/" \
  -F "image=@/path/to/photo.jpg" \
  -F "is_primary=false" \
  -H "Authorization: Token <token>"

Nota: puede apoyarse del portal administrativo para gestionar imágenes de una manera más amigable.

Response 201 (application/json)ejemplo:

{
  "id": 34,
  "landmark": 12,
  "image_url": "/media/landmarks/12/secondary_34.jpg",
  "is_primary": false,
  "uploaded_at": "2025-10-12T15:00:00Z"
}

Errores comunes:

  • 400 si faltan campos o tipo de archivo inválido.
  • 404 si landmark_id no existe.
  • 413 Payload Too Large si el archivo excede límites.

Observaciones:

  • Asegurarse de validar el tipo MIME y limitar tamaño.
  • Usar ImageField con Pillow para validación y generación de thumbnails si se requiere.

5) GET /stations/

Nombre: StationListView Método: GET Descripción: Lista estaciones definidas en el sistema. Debe devolver colección paginada con datos relevantes.

Query params (opcionales):

  • page, page_size
  • near (lat,lng) — para ordenar por proximidad
  • bbox — para filtrar área

Response 200 (application/json)ejemplo:

{
  "count": 12,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 1,
      "name": "Estación Norte",
      "description": "Punto de encuentro",
      "lat": 11.002,
      "lng": -74.852,
      "capacity": 50
    },
    ...
  ]
}

Errores comunes:

  • 400 por parámetros inválidos.

6) POST /stations/create/

Nombre: StationCreateView Método: POST Descripción: Crea una nueva estación.

Request (application/json)ejemplo:

{
  "name": "Estación Sur",
  "description": "Descripción",
  "lat": 11.003,
  "lng": -74.853,
  "capacity": 20
}

Response 201 (application/json)ejemplo:

{
  "id": 13,
  "name": "Estación Sur",
  "lat": 11.003,
  "lng": -74.853
}

Errores comunes:

  • 400 si faltan campos requeridos o lat/lng inválidos.

7) POST /api/user-local/

Nombre: UserLocalCreateView Método: POST Descripción: Crea un usuario local. Útil para asociar recorridos y comentarios a un identificador local.

Request (application/json)ejemplo:

{
  "username": "visitante_123",
  "display_name": "Andrés",
  "metadata": { "device": "android", "app_version": "0.1.0" }
}

Response 201 (application/json):

{
  "id": "local_abc123",
  "username": "visitante_123",
  "display_name": "Andrés",
  "created_at": "2025-10-12T15:10:00Z"
}

Errores comunes:

  • 400 campos requeridos faltantes.

Observaciones:

  • Decidir si UserLocal representa un modelo persistente o una entidad temporal. Para métricas y comentarios es conveniente persistir un identificador.

8) POST /api/comments/create/

Nombre: LandmarkCommentCreateView Método: POST Descripción: Crea un comentario asociado a un hito (landmark). Se usa por la app al finalizar un recorrido o al interactuar con información del hito.

Request (application/json)ejemplo:

{
  "landmark_id": 12,
  "user_id": "local_abc123", // o user: {id, username}
  "rating": 4, // opcional: calificación numérica
  "comment": "Me gustó mucho la historia del lugar."
}

Response 201 (application/json)ejemplo:

{
  "id": 55,
  "landmark": 12,
  "user_id": "local_abc123",
  "rating": 4,
  "comment": "Me gustó mucho la historia del lugar.",
  "created_at": "2025-10-12T15:15:00Z"
}

Errores comunes:

  • 400 si landmark_id o comment faltan.
  • 404 si landmark_id no existe.

Modelos (estructura sugerida / inferida)

A continuación propongo los campos más probables para cada entidad según la funcionalidad; revisa y ajusta según tus modelos reales.

Modelo: Landmark

  • id: AutoField
  • external_id: CharField (opcional)
  • name: CharField
  • slug: SlugField (opcional)
  • description: TextField
  • lat: FloatField
  • lng: FloatField
  • category: CharField (mood tags / categories)
  • main_image: ImageField (opcional)
  • secondary_images: ManyToMany -> LandmarkImage o relación a tabla LandmarkImage
  • created_at, updated_at
  • meta: JSONField (opcional para datos adicionales)

Modelo: LandmarkImage

  • id
  • landmark: ForeignKey(Landmark)
  • image: ImageField
  • is_primary: BooleanField
  • alt: CharField
  • uploaded_at

Modelo: Station

  • id
  • name
  • description
  • lat, lng
  • capacity (int)
  • created_at

Modelo: UserLocal (o Visitor)

  • id (string o uuid)
  • username
  • display_name
  • metadata: JSONField
  • created_at

Modelo: LandmarkComment

  • id
  • landmark: ForeignKey(Landmark)
  • user: ForeignKey(UserLocal) (o nullable si anónimo)
  • rating: IntegerField (opcional)
  • comment: TextField
  • approved: BooleanField (por moderación)
  • created_at

Modelo: EmotionalRoute (opcional, si se persisten)

  • id
  • mood
  • duration_minutes
  • user (FK opcional)
  • landmarks: ManyToMany(Landmark, through=RouteSequence) con orden/sequence
  • geojson: JSONField
  • created_at

Portal administrativo (Django Admin)

  • El backend aprovecha el admin de Django para gestionar:

    • Hitos, imágenes, estaciones, comentarios y usuarios locales.
  • Recomiendo usar list_display, search_fields y filtros por category y created_at.

  • Añadir acciones admin para aprobar comentarios en lote.

Dentro de la carpeta /docs va a encontrar un video explicativo de cómo usar el portal administrativo. ademas anexo las credenciales para dicho portal.

  • Usuario: admin
  • Contraseña: admin123

Validaciones y reglas de negocio importantes

  • Lat/Lng: validar rango válido (lat ∈ [-90,90], lng ∈ [-180,180]).
  • Duración de rutas: rango mínimo/máximo (ej. 5–240 min).
  • Subida de imágenes: validar tamaño y tipo MIME (jpg/png), generar thumbnails.
  • Comentarios: limitar longitud, sanitizar contenido y asociar moderación.
  • Bulk create: validar por item y devolver resultados parciales (no fallar todo por un item inválido).

Pautas de respuesta y formato (consistencia)

  • Usar siempre campos en snake_case en JSON para consistencia (duration_minutes, start_location).
  • Incluir id numérico y url o detail_url cuando aplique para facilitar hipermedia.
  • Para colecciones usar paginación estándar {count, next, previous, results}.

Qué he supuesto y por qué (transparencia)

  • Estructura de modelos y campos: inferida de las rutas y nombres de vistas — debes verificar los nombres exactos de campos en models.py.
  • Formato exacto de emotional-route response: propuesto para máxima utilidad (IDs, sequence y geojson). Si tu vista actual devuelve otra cosa, puedo adaptar la documentación al formato real.
  • Autenticación: no se especifica en urls.py; documenté endpoints como abiertos y propuse cómo protegerlos si se requiere.
  • Bulk create y GeoJSON: comportamientos estándar asumidos (bulk JSON array y FeatureCollection respectivamente).

Conclusión

Este documento ofrece una especificación técnica completa y utilizable. Permite a desarrolladores frontend y otros integrarse con el backend de Rutas Vivas de manera efectiva, entendiendo qué esperar de cada endpoint, cómo interactuar con ellos y qué validaciones se aplican.


© 2025 — Rutas Vivas Service — Documentación API (español técnico)

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published