Aufbau robuster GraphQL-APIs in Python mit Graphene und Strawberry
Daniel Hayes
Full-Stack Engineer · Leapcell

Einleitung: Die Evolution des API-Designs
In der weiten Landschaft der Backend-Entwicklung dienen APIs als entscheidende Kommunikationsbrücke zwischen verschiedenen Softwarekomponenten. Traditionell haben RESTful-APIs diesen Bereich dominiert und einen gut verstandenen und weit verbreiteten Architekturstil angeboten. Da Anwendungen jedoch zunehmend komplexer und datenhungriger werden, sind die Einschränkungen von REST, wie das Über- oder Unterabrufen von Daten und die Notwendigkeit mehrerer Roundtrips, offensichtlich geworden. Hier kommt GraphQL ins Spiel und bietet eine effizientere, flexiblere und leistungsfähigere Alternative. GraphQL ermöglicht es Clients, die benötigten Daten präzise zu definieren, sodass ein einziger API-Endpunkt vielfältige Client-Anforderungen bedienen kann. Für Python-Entwickler haben sich zwei namhafte Bibliotheken, Graphene-Django und Strawberry, als ausgezeichnete Wahl für den Aufbau robuster GraphQL-APIs herauskristallisiert. Dieser Artikel wird diese leistungsstarken Tools untersuchen, ihre Kernkonzepte und praktische Implementierung analysieren und die Szenarien, in denen sie glänzen, und Sie letztendlich beim Aufbau besserer, effizienterer APIs leiten.
Grundprinzipien von GraphQL verstehen
Bevor wir uns mit den Besonderheiten von Graphene-Django und Strawberry befassen, wollen wir ein grundlegendes Verständnis der Kernkonzepte von GraphQL schaffen. Diese Begriffe sind grundlegend für die Gestaltung und Interaktion mit jeder GraphQL-API.
Schema Definition Language (SDL)
GraphQL setzt auf ein starkes Typsystem, das mit seiner Schema Definition Language (SDL) definiert wird. Die SDL beschreibt die verfügbaren Daten, ihre Typen, Beziehungen und die Operationen (Abfragen, Mutationen, Abonnements), die ausgeführt werden können. Sie fungiert als Vertrag zwischen Client und Server und gewährleistet Datenintegrität und vorhersehbare Antworten.
Abfragen zum Abrufen von Daten
Abfragen sind die Art und Weise, wie Clients Daten von einem GraphQL-Server anfordern. Im Gegensatz zu REST, wo Clients auf feste Ressourcen zugreifen, ermöglichen GraphQL-Abfragen Clients, genau anzugeben, welche Felder und verschachtelten Beziehungen sie benötigen, wodurch Über- und Unterabfragen von Daten minimiert werden.
Mutationen zur Datenmanipulation
Mutationen werden verwendet, um Daten auf dem Server zu ändern. Ähnlich wie Abfragen haben Mutationen auch eine gut definierte Struktur, die die Eingabeargumente und den erwarteten Rückgabetyp nach der Datenmodifikation angibt. Dies gewährleistet eine vorhersehbare und kontrollierte Datenaktualisierung.
Typen und Felder
Das Herzstück des GraphQL-Schemas sind Typen, die die Struktur der Daten definieren. Typen bestehen aus Feldern, die jeweils einen bestimmten Datentyp (z. B. String, Int, Boolean, benutzerdefinierte Objekttypen) haben. Diese Typen und Felder sind die Bausteine Ihrer GraphQL-API.
Resolver: Schema mit Daten verbinden
Resolver sind Funktionen, die für das Abrufen der tatsächlichen Daten für jedes Feld eines Typs verantwortlich sind. Wenn eine GraphQL-Abfrage eingeht, durchläuft der Server das Schema und ruft den entsprechenden Resolver für jedes angeforderte Feld auf, um die entsprechenden Daten vom Backend (z. B. einer Datenbank, einer anderen API oder einem In-Memory-Datenspeicher) abzurufen.
Eingabeobjekte für strukturierte Argumente
Eingabeobjekte sind spezielle Objekttypen, die als Argumente in Mutationen oder komplexen Abfragen verwendet werden. Sie ermöglichen es Clients, strukturierte Daten als einzelnes Argument zu übergeben, wodurch API-Aufrufe sauberer und organisierter werden.
Aufbau von GraphQL-APIs mit Graphene-Django und Strawberry
Nachdem wir nun die grundlegenden GraphQL-Konzepte verstanden haben, wollen wir untersuchen, wie Graphene-Django und Strawberry in Python-Frameworks integriert werden, um leistungsstarke GraphQL-APIs zu erstellen.
Graphene-Django für Django-Projekte
Graphene-Django integriert GraphQL nahtlos in Ihre Django-Anwendungen. Es nutzt das ORM und das Modellsystem von Django, um automatisch einen Großteil Ihres GraphQL-Schemas zu generieren, was den Boilerplate-Code erheblich reduziert.
Einrichten von Graphene-Django
Installieren Sie zuerst Graphene-Django:
pip install graphene-django
Fügen Sie graphene_django
zu Ihren INSTALLED_APPS
in settings.py
hinzu:
# settings.py INSTALLED_APPS = [ # ... 'graphene_django', ]
Definieren Sie Ihr GraphQL-Schema in einer Datei schema.py
innerhalb Ihrer App:
# myapp/schema.py import graphene from graphene_django.types import DjangoObjectType from .models import Author, Book class AuthorType(DjangoObjectType): class Meta: model = Author fields = ('id', 'name', 'books') class BookType(DjangoObjectType): class Meta: model = Book fields = ('id', 'title', 'published_date', 'author') class Query(graphene.ObjectType): all_authors = graphene.List(AuthorType) author_by_id = graphene.Field(AuthorType, id=graphene.Int()) all_books = graphene.List(BookType) def resolve_all_authors(root, info): return Author.objects.all() def resolve_author_by_id(root, info, id): try: return Author.objects.get(pk=id) except Author.DoesNotExist: return None def resolve_all_books(root, info): return Book.objects.all() class CreateAuthor(graphene.Mutation): class Arguments: name = graphene.String(required=True) author = graphene.Field(AuthorType) @classmethod def mutate(cls, root, info, name): author = Author(name=name) author.save() return CreateAuthor(author=author) class Mutation(graphene.ObjectType): create_author = CreateAuthor.Field() schema = graphene.Schema(query=Query, mutation=Mutation)
Konfigurieren Sie schließlich Ihre urls.py
, um den GraphQL-Endpunkt verfügbar zu machen:
# project/urls.py from django.contrib import admin from django.urls import path from graphene_django.views import GraphQLView from myapp.schema import schema urlpatterns = [ path('admin/', admin.site.urls), path("graphql/", GraphQLView.as_view(graphiql=True, schema=schema)), ]
Diese Einrichtung stellt einen /graphql
-Endpunkt bereit, der oft mit GraphiQL (einer In-Browser-IDE für GraphQL) für einfache API-Erkundung und -Tests aktiviert ist.
Graphene-Django-Anwendungen
Graphene-Django ist ideal für bestehende Django-Projekte, die eine GraphQL-API bereitstellen müssen. Seine starke Integration mit Django-Modellen und dem ORM vereinfacht die Schemagenerierung aus Django-Modellen und macht es besonders effizient für datenintensive Anwendungen. Es eignet sich hervorragend zum Erstellen von Single-Page-Anwendungen (SPAs) oder mobilen Backends, die eine feingranulare Kontrolle über das Datenabrufen erfordern.
Strawberry für FastAPI und Flask
Strawberry bietet einen modernen, typ-hint-freundlichen Ansatz zum Erstellen von GraphQL-APIs in Python. Es eignet sich hervorragend für High-Performance-Frameworks wie FastAPI und kann auch in Flask integriert werden. Die Verwendung von Python-Typ-Hints macht Schemata explizit und hilft, Fehler während der Entwicklung zu erkennen.
Einrichten von Strawberry mit FastAPI
Installieren Sie zuerst Strawberry und FastAPI:
pip install strawberry-graphql "fastapi[all]" uvicorn
Definieren Sie Ihr Strawberry-Schema in einer Datei main.py
:
# main.py import datetime import strawberry from fastapi import FastAPI from typing import List, Optional @strawberry.type class Author: id: int name: str books: List["Book"] @strawberry.type class Book: id: int title: str published_date: datetime.date author: Author # In-memory Datenspeicher für die Demonstration authors_db = { 1: Author(id=1, name="Jane Doe", books=[]), 2: Author(id=2, name="John Smith", books=[]), } books_db = { 101: Book(id=101, title="The First Book", published_date=datetime.date(2020, 1, 1), author=authors_db[1]), 102: Book(id=102, title="Another Story", published_date=datetime.date(2021, 5, 10), author=authors_db[1]), 103: Book(id=103, title="Code Magic", published_date=datetime.date(2022, 3, 15), author=authors_db[2]), } # Beziehungen aktualisieren authors_db[1].books.extend([books_db[101], books_db[102]]) authors_db[2].books.append(books_db[103]) @strawberry.type class Query: @strawberry.field def hello(self) -> str: return "Hello World" @strawberry.field def all_authors(self) -> List[Author]: return list(authors_db.values()) @strawberry.field def author_by_id(self, id: int) -> Optional[Author]: return authors_db.get(id) @strawberry.field def all_books(self) -> List[Book]: return list(books_db.values()) @strawberry.field def total_books(self) -> int: return len(books_db) @strawberry.input class CreateAuthorInput: name: str @strawberry.type class Mutation: @strawberry.mutation def create_author(self, author_input: CreateAuthorInput) -> Author: new_id = max(authors_db.keys()) + 1 if authors_db else 1 new_author = Author(id=new_id, name=author_input.name, books=[]) authors_db[new_id] = new_author return new_author schema = strawberry.Schema(query=Query, mutation=Mutation) app = FastAPI() app.add_route("/graphql", strawberry.asgi.GraphQL(schema, graphiql=True))
Führen Sie die FastAPI-Anwendung aus:
uvicorn main:app --reload
Dies startet einen Server, normalerweise unter http://127.0.0.1:8000/graphql
, von wo aus Sie auf den GraphQL-Endpunkt mit GraphiQL zugreifen können.
Strawberry-Anwendungen
Strawberry ist eine ausgezeichnete Wahl für neue Projekte, insbesondere für solche, die moderne Python-Funktionen wie Typ-Hints nutzen. Der Framework-agnostische Kern ermöglicht die Integration mit verschiedenen ASGI/WSGI-Frameworks über FastAPI und Flask hinaus. Es eignet sich besonders gut für Microservices oder Anwendungen, bei denen eine explizite Schema-Definition und Typsicherheit hohe Priorität haben.
Abwägungen und Überlegungen
Sowohl Graphene-Django als auch Strawberry bieten robuste Lösungen für den Aufbau von GraphQL-APIs in Python, bedienen aber leicht unterschiedliche Bedürfnisse:
- Django-Integration: Graphene-Django bietet eine engere Integration mit dem ORM von Django und ist damit eine natürliche Wahl für bestehende Django-Anwendungen. Es vereinfacht die Schemagenerierung aus Django-Modellen.
- Typ-Hints und modernes Python: Strawberry nutzt moderne Python-Funktionen, insbesondere Typ-Hints, was zu besser lesbarem, wartbarem Code und besserer IDE-Unterstützung führt.
- Framework-Agnostisch: Strawberry ist Framework-agnostischer und integriert sich leicht in FastAPI, Flask und andere ASGI/WSGI-Frameworks. Graphene kann sich auch in andere Frameworks integrieren, aber seine stärkste Synergie ist mit Django.
- Boilerplate: Graphene-Django kann bei der direkten Arbeit mit Django-Modellen aufgrund seiner automatischen Feldgenerierung als weniger Boilerplate empfunden werden. Strawberry erfordert zwar explizite Schritte, erfordert aber möglicherweise etwas mehr manuelle Verdrahtung für größere Schemata, obwohl diese Eindeutigkeit oft mit Klarheit und Wartbarkeit honoriert wird.
- Leistung: Für sehr leistungsstarke Szenarien kann FastAPI mit Strawberry aufgrund der asynchronen Natur von FastAPI und der effizienten Anfragebehandlung einen Vorteil bieten.
Letztendlich hängt die Wahl zwischen Graphene-Django und Strawberry oft vom vorhandenen Projekt-Stack und den architektonischen Vorlieben ab. Wenn Sie in Django fest verwurzelt sind, ist Graphene-Django eine einfache Wahl. Wenn Sie einen neuen Dienst mit FastAPI erstellen oder explizite Typdefinitionen bevorzugen, ist Strawberry möglicherweise die bessere Wahl.
Fazit: Die Zukunft der Dateninteraktion gestalten
Der Aufbau von GraphQL-APIs mit Graphene-Django oder Strawberry ermöglicht es Entwicklern, effiziente, flexible und leistungsstarke Datenzugriffsschichten für ihre Anwendungen zu erstellen. Durch die Nutzung der Prinzipien von GraphQL und die Nutzung der Stärken dieser Python-Bibliotheken können Sie Clients eine beispiellose Kontrolle über ihre Datenanforderungen bieten, was zu schnelleren Entwicklungszyklen und verbesserten Benutzererlebnissen führt. Egal, ob Sie einen bestehenden Django-Monolithen erweitern oder einen hochmodernen FastAPI-Microservice entwickeln, das GraphQL-Ökosystem von Python bietet ausgefeilte Werkzeuge, um die APIs von morgen zu erstellen. Diese Bibliotheken rationalisieren die komplexe Aufgabe der API-Entwicklung und machen die Dateninteraktion für Clients und Entwickler gleichermaßen intuitiver und robuster.