Pages de profil de pilote avec statistiques de carrière
Combinez le profil d'un pilote et ses totaux de carrière dans une seule fiche, identifiée par le numéro de course.
8 min de lecture
Les applications de fans, les jeux fantasy et les sites d’actualité ont tous besoin d’une page par pilote. Deux appels suffisent pour une fiche de profil : le pilote et ses totaux de carrière.
Les deux appels
GET /riders/93
GET /riders/93/career-stats
/riders/{rider_number} renvoie le profil :
{
"rider_number": 93,
"full_name": "Marc Márquez",
"nationality": "Spain",
"flag": "🇪🇸",
"birth_date": "1993-02-17",
"height_cm": 168,
"weight_kg": 59,
"team_name": "Gresini Racing MotoGP",
"image_url": null
}
/riders/{rider_number}/career-stats renvoie les totaux :
{
"rider_number": 93,
"rider_name": "Marc Márquez",
"total_wins": 44,
"total_podiums": 66,
"total_points": 1302,
"world_titles": 2,
"total_races": 118
}
Les totaux de carrière sont calculés à partir des saisons disponibles dans l’API, pas sur toute la carrière d’un pilote. Indiquez-le dans le libellé, par exemple « Depuis 2024 ».
Récupérer les deux en parallèle
import os
from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass
from datetime import date
import requests
HOST = "motogp-api-championship-data-statistics.p.rapidapi.com"
HEADERS = {"X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"], "X-RapidAPI-Host": HOST}
def get(path: str) -> dict:
res = requests.get(f"https://{HOST}{path}", headers=HEADERS, timeout=10)
res.raise_for_status()
return res.json()["data"]
@dataclass(frozen=True)
class RiderCard:
number: int
name: str
flag: str
team: str
age: int
wins: int
podiums: int
titles: int
races: int
@property
def podium_rate(self) -> float:
return self.podiums / self.races if self.races else 0.0
def age_on(birth: str, today: date) -> int:
born = date.fromisoformat(birth)
return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
def rider_card(number: int) -> RiderCard:
with ThreadPoolExecutor(max_workers=2) as pool:
profile_f = pool.submit(get, f"/riders/{number}")
stats_f = pool.submit(get, f"/riders/{number}/career-stats")
profile, stats = profile_f.result(), stats_f.result()
return RiderCard(
number=profile["rider_number"],
name=profile["full_name"],
flag=profile["flag"],
team=profile["team_name"],
age=age_on(profile["birth_date"], date.today()),
wins=stats["total_wins"],
podiums=stats["total_podiums"],
titles=stats["world_titles"],
races=stats["total_races"],
)
card = rider_card(93)
print(f"{card.flag} #{card.number} {card.name} — {card.team}, {card.age}")
print(f"{card.wins} wins, {card.podiums} podiums in {card.races} races ({card.podium_rate:.0%})")
Construire les pages d’index
Les pages de profil ont besoin d’une liste pour y renvoyer :
| Page | Endpoint |
|---|---|
| Grille de cette saison | GET /riders/seasons/{year}?category=MOTOGP |
| Pilotes par pays | GET /riders/nationality/{nationality} (ex. Italy) |
| Tous les pilotes de la base | GET /riders?page=1&size=200 |
Utilisez rider_number comme slug d’URL (/riders/93/) : c’est ce que les fans recherchent.
Gérer les données manquantes
image_urlpeut valoirnull. Affichez le numéro de course dans un badge coloré plutôt qu’une image cassée.- Un numéro inutilisé renvoie
404— affichez une page « pilote introuvable » plutôt qu’une erreur. - Les pilotes changent parfois de numéro d’une saison à l’autre. Si vous stockez des favoris, stockez le numéro avec la saison d’où il provient.