FastAPI 之 GraphQL#

参考:GraphQL

因为 FastAPI 是基于 ASGI 标准的,所以集成任何与 ASGI 兼容的 GraphQL 库都非常容易。

在同一个应用程序中,可以将普通的 FastAPI 路径操作与 GraphQL 结合使用。

小技巧

  • GraphQL解决了一些非常具体的用例。

  • 与普通 web API 相比,它有优点也有缺点。

  • 确保您评估了用例的好处是否弥补了缺点。🤓

FastAPI:GraphQL + Strawberry#

如果你需要或者想要使用 GraphQL, Strawberry 是推荐的库,因为它的设计最接近 FastAPI 的设计,它都是基于类型注释的。

下面是关于如何将 Strawberry 与 FastAPI 集成的小样例:

!pip install -q fastapi uvicorn strawberry
  error: subprocess-exited-with-error
  
  × python setup.py egg_info did not run successfully.
   exit code: 1
  ╰─> [14 lines of output]
      error: Multiple top-level packages discovered in a flat-layout: ['artwork', 'strawberry'].
      
      To avoid accidental inclusion of unwanted files or directories,
      setuptools will not proceed with this build.
      
      If you are trying to create a single distribution with multiple packages
      on purpose, you should not rely on automatic discovery.
      Instead, consider the following options:
      
      1. set up custom discovery (`find` directive with `include` or `exclude`)
      2. use a `src-layout`
      3. explicitly set `py_modules` or `packages` with a list of names
      
      To find more information, look for "package discovery" on setuptools docs.
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.
import strawberry
from fastapi import FastAPI
from strawberry.asgi import GraphQL


@strawberry.type
class User:
    name: str
    age: int


@strawberry.type
class Query:
    @strawberry.field
    def user(self) -> User:
        return User(name="Patrick", age=100)


schema = strawberry.Schema(query=Query)


graphql_app = GraphQL(schema)

app = FastAPI()
app.add_route("/graphql", graphql_app)
app.add_websocket_route("/graphql", graphql_app)

更多样例可以参考:strawberry-fastapi

if __name__ == "__main__":
    import asyncio
    import uvicorn
    config = uvicorn.Config(app, port=3005, reload=False,)
    server = uvicorn.Server(config)
    loop = asyncio.get_event_loop()
    loop.create_task(server.serve())