FastAPIとDjangoでStrawberryを使ってモダンなGraphQL APIを構築する
Emily Parker
Product Engineer · Leapcell

簡単にするためインメモリデータベースを使用
BOOKS_DB = []
@strawberry.type class Book: id: strawberry.ID title: str author: str year: int
@strawberry.input class BookInput: title: str author: str year: int
@strawberry.type class Query: @strawberry.field def hello(self) -> str: return "Hello World"
@strawberry.field
def books(self) -> list[Book]:
return BOOKS_DB
@strawberry.field
def book(self, id: strawberry.ID) -> Book | None:
for book in BOOKS_DB:
if book.id == id:
return book
return None
@strawberry.type class Mutation: @strawberry.mutation def add_book(self, book_data: BookInput) -> Book: new_book = Book(id=strawberry.ID(str(len(BOOKS_DB) + 1)), **book_data.dict) BOOKS_DB.append(new_book) return new_book
@strawberry.mutation
def update_book(self, id: strawberry.ID, book_data: BookInput) -> Book | None:
for i, book in enumerate(BOOKS_DB):
if book.id == id:
updated_book = Book(id=id, **book_data.__dict__)
BOOKS_DB[i] = updated_book
return updated_book
return None
@strawberry.mutation
def delete_book(self, id: strawberry.ID) -> bool:
global BOOKS_DB
initial_len = len(BOOKS_DB)
BOOKS_DB = [book for book in BOOKS_DB if book.id != id]
return len(BOOKS_DB) < initial_len
schema = strawberry.Schema(query=Query, mutation=Mutation)
app = FastAPI() app.add_route("/graphql", GraphQL(schema))
To run this: uvicorn main --reload
</code></pre>
<p>このFastAPIの例では:</p> <ol> <li><code>@strawberry.type</code>を使用して、<code>Book</code>をSQLAlchemy型として定義します。</li> <li><code>Query</code>および<code>Mutation</code>クラスは、利用可能な操作を定義します。</li> <li><code>Query</code>および<code>Mutation</code>内の各フィールドは、それぞれ<code>@strawberry.field</code>または<code>@strawberry.mutation</code>でデコレートされ、GraphQLで公開されるフィールド/操作になります。</li> <li>型ヒントは、StrawberryがGraphQL型を推論するために不可欠です。</li> <li><code>strawberry.asgi</code>の<code>GraphQL</code>を使用して、StrawberryスキーマをFastAPIに統合します。</li> </ol> <p>通常、<code>http://127.0.0.1:8000/graphql</code>でGraphQLプレイグラウンドにアクセスして、クエリやミューテーションを送信できます。</p> <strong>例クエリ:</strong> <pre><code class="language-graphql"> query { books { id title author } } </code></pre> <strong>例ミューテーション:</strong> <pre><code class="language-graphql"> mutation AddNewBook { addBook(bookData: {title: "The Great Gatsby", author: "F. Scott Fitzgerald", year: 1925}) { id title author } } </code></pre> <h4 id="example-with-django">Djangoでの例</h4> <p>StrawberryとDjangoの統合は同様に簡単で、多くの場合<code>Django Models</code>を型定義に活用します。</p> <p>まず、必要なライブラリをインストールします。</p> <pre><code class="language-bash">pip install django strawberry-graphql "strawberry-graphql-django>=0.9" </code></pre> <p><code>books</code>という名前のDjangoプロジェクトとアプリがあると仮定します。<code>Book</code>モデルを定義します。</p> <pre><code class="language-python"># books/models.py from django.db import modelsclass Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=200) year = models.IntegerField()
def __str__(self):
return self.title
</code></pre>
<p>次に、<code>books/schema.py</code>のようなファイルでStrawberryスキーマを定義します。</p> <pre><code class="language-python"># books/schema.py import strawberry from strawberry_django.views import GraphQLView from .models import BookDjangoモデルから型を自動生成するためにstrawberry_djangoを使用
@strawberry.django.type(Book) class BookType: id: strawberry.ID title: str author: str year: int
@strawberry.input class BookInput: title: str author: str year: int
@strawberry.type class Query: @strawberry.field def hello(self) -> str: return "Hello from Django!"
@strawberry.field
def books(self) -> list[BookType]:
return Book.objects.all()
@strawberry.field
def book(self, id: strawberry.ID) -> BookType | None:
try:
return Book.objects.get(pk=id)
except Book.DoesNotExist:
return None
@strawberry.type class Mutation: @strawberry.mutation def add_book(self, book_data: BookInput) -> BookType: new_book = Book.objects.create(**book_data.dict) return new_book
@strawberry.mutation
def update_book(self, id: strawberry.ID, book_data: BookInput) -> BookType | None:
try:
book_to_update = Book.objects.get(pk=id)
for key, value in book_data.__dict__.items():
setattr(book_to_update, key, value)
book_to_update.save()
return book_to_update
except Book.DoesNotExist:
return None
@strawberry.mutation
def delete_book(self, id: strawberry.ID) -> bool:
try:
book_to_delete = Book.objects.get(pk=id)
book_to_delete.delete()
return True
except Book.DoesNotExist:
return False
schema = strawberry.Schema(query=Query, mutation=Mutation) </code></pre>
<p>最後に、GraphQLエンドポイントを公開するためにDjangoの<code>urls.py</code>を設定します。</p> <pre><code class="language-python"># myproject/urls.py (またはアプリのurls.py) from django.contrib import admin from django.urls import path from strawberry_django.views import GraphQLView from books.schema import schemaurlpatterns = [ path("admin/", admin.site.urls), path("graphql", GraphQLView.as_view(schema=schema)), ] </code></pre>
<p>Djangoアプリケーションを実行するには:</p> <pre><code class="language-bash">python manage.py makemigrations books python manage.py migrate python manage.py runserver </code></pre> <p>Django統合は、<code>@strawberry.django.type</code>のようなヘルパー関数を使用して、DjangoモデルをGraphQL型に自動的にマッピングし、ボイラープレートを削減する<code>strawberry-graphql-django</code>から恩恵を受けます。</p> <h3 id="application-scenarios">アプリケーションシナリオ</h3> <ul> <li><strong>シングルページアプリケーション(SPA)およびモバイルアプリ</strong>:GraphQLは、単一のリクエストですべての必要なデータを取得できるため、ネットワーク往復を削減し、パフォーマンスを向上させることができるため、これらのアプリケーションに最適です。</li> <li><strong>マイクロサービスアーキテクチャ</strong>:GraphQLはAPIゲートウェイとして機能し、さまざまなマイクロサービスからデータを集約し、クライアントに統一されたAPIを公開できます。</li> <li><strong>公開API</strong>:RESTに加えて、またはそれに代わるGraphQLエンドポイントを提供することで、コンシューマーは受信するデータに対してより多くの柔軟性と制御を得ることができます。</li> <li><strong>リアルタイムデータ</strong>:Strawberryはサブスクリプションをサポートしており、WebSocketsを使用してリアルタイムデータ更新を可能にし、チャットアプリケーション、ライブダッシュボード、または通知に適しています。</li> </ul> <h2 id="conclusion">結論</h2> <p>Strawberryは、FastAPIやDjangoといった人気のフレームワークとシームレスに統合された、堅牢なGraphQL APIを構築するための非常にPythonicで効率的な方法を提供します。そのコードファーストアプローチ、強力な型ヒント、優れたコミュニティサポートにより、開発者は柔軟でパフォーマンスの高いデータ取得レイヤーを作成できます。Strawberryを活用することで、開発者は従来のREST APIの制限を克服し、クリーンで保守性の高いバックエンドコードベースを維持しながら、クライアントに正確なデータ取得機能を提供できます。最終的に、Strawberryは、強力でありながら使いやすい、将来性のあるAPIの構築に役立ちます。</p>