← Tous les guides

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 :

PageEndpoint
Grille de cette saisonGET /riders/seasons/{year}?category=MOTOGP
Pilotes par paysGET /riders/nationality/{nationality} (ex. Italy)
Tous les pilotes de la baseGET /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_url peut valoir null. 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.
Guide suivant → Calendrier de la saison, prochaine course et résultats