hcornet 0b1b6dd5b2
build / build (push) Successful in 1m12s
correction vignette
2026-09-22 18:26:44 +02:00
2026-09-21 17:43:42 +02:00
2026-09-22 15:09:24 +02:00
fix
2026-09-22 16:33:32 +02:00
2026-09-22 18:26:44 +02:00
2026-09-21 17:43:42 +02:00
2026-09-21 17:43:42 +02:00
2026-09-21 17:43:42 +02:00
2026-09-21 17:43:42 +02:00
2026-09-21 18:30:14 +02:00
2026-09-21 17:43:42 +02:00
2026-09-22 13:34:17 +02:00
2026-09-21 17:43:42 +02:00
2026-09-21 18:27:03 +02:00

api-python-001

Réécriture en Python (FastAPI + SQLite) de afuh/rick-and-morty-api (Node.js/Express + MongoDB) — https://api-python-001.tips-of-mine.com

Correspondance avec l'original

Original (Node.js) Ici (Python)
server.js (Express) app/main.py (FastAPI)
routes/ + handlers/ app/routers/ (+ common.py : pagination, filtres, ids multiples)
models/ (Mongoose / MongoDB) app/models.py (SQLAlchemy / SQLite)
utils/helpers.js (messages) app/errors.py
lecture seule + POST / PUT, DELETE protégé par X-API-Key
images/ servies sur /api/character/avatar/N.jpeg idem, fichiers envoyés par upload dans data/avatars
— site web de consultation (/, Jinja2, sans JavaScript)
graphql/ chantier suivant

Endpoints

Méthode Chemin
GET /api — index des ressources
GET /api/{character,location,episode} — 20 par page, ?page=N + filtres
GET /api/{ressource}/1, /1,2,3, /[1,2,3]
POST /api/{ressource} — id et created facultatifs (conservés si fournis)
PUT /api/{ressource}/{id} — remplacement complet (id/created du corps ignorés)
DELETE /api/{ressource}/{id} — en-tête X-API-Key
PUT /api/episode/{id}/characters/{character_id} — corps {"role": "major"|"minor"|"mentioned"|null, "died": false} : rattache le personnage si besoin et fixe son rôle
PUT /api/episode/{id}/locations/{location_id} — relie l'épisode à un lieu où il se déroule (sans effet si déjà lié)
DELETE /api/episode/{id}/locations/{location_id} — retire ce lien (X-API-Key), le lieu est conservé
PUT /api/location/{id}/parents/{parent_id} — place le lieu dans un autre (plusieurs parents possibles, sans effet si déjà lié)
DELETE /api/location/{id}/parents/{parent_id} — retire ce lien (X-API-Key), les lieux sont conservés
PUT /api/character/{id}/avatar — corps brut JPEG/PNG (2 Mo max), X-API-Key ; met à jour image
GET /api/character/avatar/{id}.jpeg (ou .png)
GET /health, /hello, /docs

Filtres (partiels, insensibles à la casse) : character name status species type gender, location name type dimension, episode name episode.

Format et relations

Réponses identiques à l'original, plus un champ modified (date de dernière modification, égale à created tant que l'objet n'a pas été modifié) ; une ressource lue en GET peut être renvoyée telle quelle en POST. Les URL (origin, location, episode, residents) sont décodées sur /api/<ressource>/<id>, quel que soit l'hôte.

  • character.episode ↔ episode.characters : une seule relation. Le champ characters d'un épisode en entrée est ignoré.

  • location.residents : liste saisie telle quelle (ordre conservé), indépendante de character.location.

  • Rôle par épisode : chaque lien personnage ↔ épisode porte un rôle (major, minor, mentioned, vide = non classé) et un indicateur died. Champs ajoutés en fin d'objet : episode_roles (character) et characters_by_role (episode : major, minor, mentioned, unclassified, dead). Un PUT de character conserve les rôles des épisodes qu'il garde.

  • Lieux d'un épisode : relation épisode ↔ location saisie via l'API ; champs ajoutés en fin d'objet : locations (episode) et episodes (location).

  • Hiérarchie des lieux : un lieu peut être contenu dans plusieurs lieux (ex. une seule « Smith Residence » sur plusieurs planètes de plusieurs dimensions). Champs ajoutés en fin d'objet : parents et children (location). En entrée, parents (URL) remplace les parents ; absent, ils sont conservés ; children est ignoré. Un parent doit être d'un niveau strictement inférieur (niveaux sautables), sinon 422 ; cycles refusés :

    Niveau Types
    0 Multiverse
    1 Dimension, Reality, Non-Diegetic Alternative Reality
    2 Planet, Dwarf planet (Celestial Dwarf), Asteroid, Star, Cluster, Quadrant, Quasar, Space, Space station, Spacecraft, Death Star, Artificially generated world
    3 Country, State, City, Fantasy town, Woods, Lake, Mount, Liquid
    4 Residence, Building, School, Restaurant, Arcade, Spa, Resort, Daycare, Customs, Police Department, Convention, Lair, Company, Theme park, Acid Plant, Menagerie, Base
    libre tout autre type (Microverse, Dream, TV, unknown…) : aucune contrainte de niveau

    dimension est calculée : noms des lieux de niveau 1 parmi le lieu et ses ancêtres (séparés par « , »), sinon la valeur saisie. Le filtre ?dimension= porte sur cette valeur calculée. Table dans app/hierarchy.py.

  • Migration : les colonnes ajoutées après la mise en production sont créées au démarrage (app/migrations.py).

Ordre d'import (n8n) : locations → episodes → characters → avatars.

Site web

/ accueil, /characters, /locations, /episodes (listes paginées + filtres) et leurs fiches /<ressource>/<id>. Fiche épisode : lieux de l'épisode en arbre indenté (lieux englobants grisés), puis personnages rangés en Major / Minor / Mentioned / Dead / Non classés ; fiche personnage : rôle par épisode ; fiche location : lieux parents et contenus, épisodes où elle apparaît. Bascule ?vue=images / ?vue=liste sur la liste des characters, les residents d'une location et la fiche épisode. Rendu serveur sans JavaScript, contenu échappé et en-tête CSP strict (les données sont saisissables via l'API).

CI/CD

.gitea/workflows/build.yml : tests (étape test du Dockerfile) puis push Harbor ${HARBOR_REGISTRY}/api-python-001/api-python-001 — main → latest + sha-xxx, tag v1.2.3 → 1.2.3, 1.2.

Déploiement SLDOKP03

mkdir -p /opt/api-python-001/data && cd /opt/api-python-001
# copier docker-compose.yml et .env.example -> .env
chown 10001:10001 data
docker compose pull && docker compose up -d
S
Description
No description provided
Readme
170 KiB
0 Stars 3 Watchers 0 Forks
Languages
Python 83.6%
HTML 15%
Dockerfile 1.4%