Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐍
Intermediaire 30 min FastAPI

FastAPI avec GraphQL

Pourquoi FastAPI avec GraphQL ?

FastAPI est une fameuse bibliothèque Python pour construire des APIs rapides et efficaces, tandis que GraphQL est un langage de requêtes et d'interrogation pour les API qui permet aux clients de demander exactement ce qu'ils ont besoin. L'utilisation de FastAPI avec GraphQL offre plusieurs avantages :

  1. Contrôle total sur la réponse : Avec GraphQL, les clients peuvent spécifier exactement le champ dont ils ont besoin. Cela réduit le temps de réponse et économise des ressources serveur.
  2. Performance optimale : Les requêtes GraphQL permettent de récupérer les données nécessaires en une seule requête, ce qui améliore la performance.
  3. Documentation générée automatiquement : FastAPI génère automatiquement une documentation interactive pour votre API, facilitant le développement et l'utilisation.

Un cas d'usage concret serait un service e-commerce où un client peut demander des informations spécifiques sur un produit, comme son prix, sa description, et les images associées, tout en évitant de récupérer des données inutiles.

Prerequis

  • Connaissances en Python (minimum 2 ans)
  • Familiarité avec FastAPI
  • Connaissance de base de GraphQL
  • Un environnement Python configuré avec pip

Outils à installer :

  • Python 3.7 ou plus récent
  • FastAPI : pip install fastapi
  • Uvicorn : pip install uvicorn (pour l'exécution du serveur)

Concepts fondamentaux

Schéma GraphQL

Un schéma GraphQL définit le type de données que votre API peut retourner et comment ces types sont liés entre eux. Voici un exemple simple :

from fastapi import FastAPI
import graphene

app = FastAPI()

class Query(graphene.ObjectType):
    hello = graphene.String(name=graphene.String(default_value="stranger"))

    def resolve_hello(self, info, name):
        return f"Hello {name}!"

schema = graphene.Schema(query=Query)

@app.get("/")
async def read_root():
    query = '{ hello(name: "World") }'
    result = schema.execute(query)
    return {"data": str(result.data)}

Mutation GraphQL

Une mutation est une requête qui modifie le state de votre application. Voici un exemple :

class Mutation(graphene.ObjectType):
    create_user = graphene.Field(User, name=graphene.String(required=True))

    def mutate(self, info, name):
        user = User(name=name)
        return CreateUser(user=user)

schema = graphene.Schema(query=Query, mutation=Mutation)

@app.post("/")
async def create_user():
    query = '''
        mutation {
            createUser(name: "John Doe") {
                user {
                    name
                }
            }
        }
    '''
    result = schema.execute(query)
    return {"data": str(result.data)}

Resolver GraphQL

Un resolver est une fonction qui définit comment récupérer les données pour un champ spécifique dans le schéma. Voici un exemple :

def resolve_user(self, info):
    # Logique pour récupérer l'utilisateur
    user = User(id=1, name="John Doe")
    return user

Query et Mutation en même temps

Vous pouvez combiner des queries et mutations dans une seule requête. Voici un exemple :

class Query(graphene.ObjectType):
    hello = graphene.String(name=graphene.String(default_value="stranger"))
    user = graphene.Field(User, id=graphene.Int(required=True))

    def resolve_hello(self, info, name):
        return f"Hello {name}!"

    def resolve_user(self, info, id):
        # Logique pour récupérer l'utilisateur
        user = User(id=id, name="John Doe")
        return user

class Mutation(graphene.ObjectType):
    create_user = graphene.Field(User, name=graphene.String(required=True))

    def mutate(self, info, name):
        user = User(name=name)
        return CreateUser(user=user)

schema = graphene.Schema(query=Query, mutation=Mutation)

@app.post("/")
async def execute_query():
    query = '''
        {
            hello(name: "World"),
            user(id: 1) {
                id
                name
            }
        }
    '''
    result = schema.execute(query)
    return {"data": str(result.data)}

Mise en pratique : projet fil rouge

Nous allons créer un simple API de blog avec FastAPI et GraphQL. L'application permettra d'afficher les articles, de les créer, de les mettre à jour et de les supprimer.

Étape 1 : Configuration du projet

Créer un nouveau répertoire pour le projet :

mkdir fastapi-graphql-blog
cd fastapi-graphql-blog

Initialiser un environnement virtuel et installer les dépendances :

python -m venv venv
source venv/bin/activate  # Sous Windows : `venv\Scripts\activate`
pip install fastapi uvicorn graphene graphene-sqlalchemy sqlalchemy

Étape 2 : Structure du projet

Créer la structure de fichiers suivante :

fastapi-graphql-blog/
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── models.py
│   └── schema.py
└── requirements.txt

Étape 3 : Configuration des modèles SQLAlchemy

Créer le fichier app/models.py :

from sqlalchemy import create_engine, Column, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class Article(Base):
    __tablename__ = 'articles'

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(255), index=True)
    content = Column(Text)

## Connexion à la base de données SQLite
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)

Étape 4 : Configuration du schéma GraphQL

Créer le fichier app/schema.py :

from fastapi import FastAPI
import graphene
from sqlalchemy.orm import Session
from .models import Article, engine, SessionLocal

app = FastAPI()

## Définition des types de données
class ArticleType(graphene.ObjectType):
    id = graphene.ID()
    title = graphene.String()
    content = graphene.String()

class Query(graphene.ObjectType):
    article = graphene.Field(ArticleType, id=graphene.Int(required=True))
    articles = graphene.List(ArticleType)

    def resolve_article(self, info, id):
        db = SessionLocal()
        article = db.query(Article).filter(Article.id == id).first()
        return article

    def resolve_articles(self, info):
        db = SessionLocal()
        articles = db.query(Article).all()
        return articles

class CreateArticleInput(graphene.InputObjectType):
    title = graphene.String(required=True)
    content = graphene.String(required=True)

class CreateArticle(graphene.Mutation):
    class Arguments:
        input = CreateArticleInput(required=True)

    article = graphene.Field(ArticleType)

    def mutate(self, info, input):
        db = SessionLocal()
        new_article = Article(title=input.title, content=input.content)
        db.add(new_article)
        db.commit()
        return CreateArticle(article=new_article)

class Mutation(graphene.ObjectType):
    create_article = CreateArticle.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)

@app.post("/")
async def execute_query():
    query = '''
        mutation {
            createArticle(input: {title: "GraphQL with FastAPI", content: "This is a sample article."}) {
                article {
                    id
                    title
                    content
                }
            }
        }
    '''
    result = schema.execute(query)
    return {"data": str(result.data)}

Étape 5 : Exécution de l'application

Lancer le serveur FastAPI :

uvicorn app.main:app --reload

Accéder à l'interface d'exploration du schéma GraphQL via http://127.0.0.1:8000/graphql.

Erreurs frequentes et debugging

1. Erreur : MissingSchemaError

Code incorrect :

schema = graphene.Schema(query=Query)

Code correct :

schema = graphene.Schema(query=Query, mutation=Mutation)

2. Erreur : TypeError: 'NoneType' object is not callable

Code incorrect :

class Mutation(graphene.ObjectType):
    create_article = CreateArticle.Field()

Code correct :

class Mutation(graphene.ObjectType):
    create_article = CreateArticle.Field()

3. Erreur : AttributeError: module 'sqlalchemy.orm' has no attribute 'Session'

Code incorrect :

from sqlalchemy.orm import SessionLocal, Session

Code correct :

from sqlalchemy.orm import sessionmaker, Session

Pour aller plus loin

  1. Optimisation des requêtes GraphQL : Explorer les directives @defer et @stream pour améliorer les performances des requêtes complexes.
  2. Intégration avec une base de données PostgreSQL : Utiliser SQLAlchemy pour connecter votre API à une base de données PostgreSQL plutôt que SQLite.
  3. Ajout d'authentification et d'autorisation : Implémenter des mécanismes d'authentification et d'autorisation pour sécuriser votre API.

Défi pratique : Ajouter une fonctionnalité qui permet de mettre à jour et de supprimer des articles via des mutations GraphQL.

Besoin d'aide sur FastAPI ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que FastAPI?
FastAPI est un framework asynchrone pour construire des API web rapides et efficaces en Python 3.7+ basé sur ASGI.
Comment puis-je intégrer GraphQL à FastAPI?
Pour intégrer GraphQL à FastAPI, vous pouvez utiliser la bibliothèque `fastapi-graphql` qui permet de définir des schémas GraphQL et d'intégrer facilement avec les routes FastAPI.
Quelles sont les principales avantages d'utiliser FastAPI avec GraphQL?
FastAPI offre une meilleure vitesse d'exécution, une validation de données forte, une génération automatique de documentation et un support intégré pour les tests. Avec GraphQL, vous pouvez récupérer exactement ce que vous voulez dans chaque requête.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.