diff --git a/website/data/category_intros/web-apis.md b/website/data/category_intros/web-apis.md index aee66d97..93305779 100644 --- a/website/data/category_intros/web-apis.md +++ b/website/data/category_intros/web-apis.md @@ -1,33 +1,31 @@ -Outside Django, declare each FastAPI endpoint with type hints. Django projects add a Python API framework on top instead: Django REST framework or Django Ninja. +Type hints alone let FastAPI validate requests and document your API. Python API frameworks for Django include Django Ninja, which reads them too. How to choose: -- Django, with CRUD endpoints over your models: Django REST framework -- Django, with endpoints declared by type hints: Django Ninja -- A new service outside Django: FastAPI -- GraphQL over Django models: Strawberry GraphQL Django -- Django, with msgspec, attrs, or dataclass schemas: django-modern-rest -- A Flask app: APIFlask +- A new API, not tied to Django or Flask: FastAPI +- Typed endpoints in a Django project: Django Ninja +- CRUD endpoints over Django models, with a browsable API: Django REST framework +- GraphQL types generated from Django models: Strawberry Django +- msgspec, attrs, or dataclass schemas on Django: django-modern-rest +- Flask resources grouped into namespaces, with Swagger docs: Flask-RESTX +- marshmallow schemas on Flask blueprints: flask-smorest +- A Flask app validated with Pydantic models or marshmallow: APIFlask +- GraphQL on FastAPI or any other framework: Strawberry - An OpenAPI spec written before the code: Connexion -- GraphQL on FastAPI, Flask, or another framework: Strawberry -- RPC between services in any language: gRPC +- Calls between services written in different languages: gRPC -Django REST framework adds serializers and a [browsable API](https://www.django-rest-framework.org/) to Django. For CRUD over your models, [group the views in a `ModelViewSet` and register it with a router](https://www.django-rest-framework.org/tutorial/quickstart/). For an OpenAPI schema, its docs [recommend drf-spectacular](https://www.django-rest-framework.org/topics/documenting-your-api/#drf-spectacular). By default, the API [allows unrestricted access](https://www.django-rest-framework.org/api-guide/permissions/#setting-the-permission-policy), so set a policy in `DEFAULT_PERMISSION_CLASSES`. +FastAPI is [based on standard Python type hints](https://fastapi.tiangolo.com/). Declare path, query, and body parameters as typed function arguments, and it validates them and serves interactive docs at `/docs`. As the app grows, split it into modules with [`APIRouter`, a "mini FastAPI"](https://fastapi.tiangolo.com/tutorial/bigger-applications/). -Django Ninja is [heavily inspired by FastAPI](https://django-ninja.dev/motivation/) and works with Django's ORM, URLs, views, and auth. You write each endpoint as a function with type hints, and it [generates the OpenAPI docs](https://django-ninja.dev/) from them. Run async views on [an ASGI server](https://django-ninja.dev/guides/async-support/). If you use Django's cookie-based auth, [keep Django's CSRF protection on](https://django-ninja.dev/reference/csrf/#use-djangos-built-in-csrf-protection). +Django Ninja was [heavily inspired by FastAPI](https://django-ninja.dev/) and integrates with Django's core and ORM. You declare parameter and body types once, as function arguments, and the interactive docs show up at `/api/docs`. For a bigger project, [create an `api.py` with a `Router` in each Django app](https://django-ninja.dev/guides/routers/). -FastAPI builds [request validation and OpenAPI docs from standard type hints](https://fastapi.tiangolo.com/), on top of Pydantic and Starlette. Install `fastapi[standard]`, which brings Uvicorn and the `fastapi` command: run `fastapi dev` while you work and [`fastapi run` in production](https://fastapi.tiangolo.com/fastapi-cli/). +Django REST framework [splits an API into](https://www.django-rest-framework.org/) serializers for the representation, viewsets for the behavior, and routers for the URLs. [Viewsets get you running quickly](https://www.django-rest-framework.org/api-guide/viewsets/) and keep URLs consistent across a large API, while plain views are more explicit. For OpenAPI schemas, its docs [recommend drf-spectacular](https://www.django-rest-framework.org/topics/documenting-your-api/). -Strawberry GraphQL Django [builds types from your Django models](https://strawberry.rocks/docs/django), while Strawberry alone [only provides a GraphQL view](https://strawberry.rocks/docs/integrations/django) for Django. Add its [query optimizer](https://strawberry.rocks/docs/django/guide/optimizer), which calls `select_related()` and `prefetch_related()` for you to avoid N+1 queries. +APIFlask has you [use `APIFlask` instead of `Flask`](https://apiflask.com/), then declare request and response schemas with [`@app.input` and `@app.output`](https://apiflask.com/usage/). flask-smorest [organizes resources as `MethodView` classes in blueprints](https://flask-smorest.readthedocs.io/en/latest/quickstart.html), with marshmallow schemas on `Blueprint.arguments` and `Blueprint.response`. Flask-RESTX [splits your app into reusable namespaces](https://flask-restx.readthedocs.io/en/latest/scaling.html), much like blueprints, and describes them for Swagger through decorators. -django-modern-rest [drops into an existing Django app](https://django-modern-rest.readthedocs.io/en/latest/) and validates both requests and responses against your schemas: msgspec, Pydantic, attrs, dataclasses, and more. Its docs [recommend always installing msgspec](https://django-modern-rest.readthedocs.io/en/latest/pages/getting-started.html#installation) to parse JSON, even when your schemas are Pydantic models. +Strawberry [builds on dataclasses and type hints](https://strawberry.rocks/docs), and FastAPI's docs [recommend it for GraphQL](https://fastapi.tiangolo.com/how-to/graphql/). Before going to production, [disable GraphiQL and introspection](https://strawberry.rocks/docs/operations/deployment), and turn on Strawberry's security extensions that limit query depth, aliases, and tokens. -APIFlask is a [thin wrapper on Flask](https://apiflask.com/migrations/flask/): swap `Flask` for `APIFlask` and `Blueprint` for `APIBlueprint`, and your [Flask extensions keep working](https://apiflask.com/comparison/#apiflask-vs-fastapi). Declare each endpoint's input and output with `@app.input()` and `@app.output()`, as [marshmallow schemas or Pydantic models](https://apiflask.com/), and APIFlask generates the OpenAPI docs from them. +Strawberry Django [creates GraphQL types from your Django models](https://strawberry.rocks/docs/django). Add its [`DjangoOptimizerExtension`](https://strawberry.rocks/docs/django/guide/optimizer), which calls `select_related()` and `prefetch_related()` for you to avoid N+1 queries. -Connexion is spec-first: you write the OpenAPI spec, and Connexion [routes and validates requests against it](https://connexion.readthedocs.io/en/latest/#why-connexion), so server and client can be built in parallel. FastAPI goes the other way, and its maintainer says it's [not meant for writing the schema first](https://github.com/fastapi/fastapi/discussions/6169). Start a new project on [`AsyncApp`](https://connexion.readthedocs.io/en/latest/quickstart.html#creating-your-application), or on `FlaskApp` to keep the Flask ecosystem. +Connexion flips the usual order: you [write the OpenAPI spec first](https://connexion.readthedocs.io/en/latest/), then the code, and Connexion validates requests against the spec. Each `operationId` in the spec [names the Python function that handles it](https://connexion.readthedocs.io/en/latest/routing.html). Start new projects on [`AsyncApp`, or on `FlaskApp` to use the Flask ecosystem](https://connexion.readthedocs.io/en/latest/quickstart.html). -Strawberry builds a GraphQL schema from [dataclasses and type hints](https://strawberry.rocks/docs), and FastAPI's docs [recommend it for GraphQL](https://fastapi.tiangolo.com/how-to/graphql/#graphql-with-strawberry). Before you deploy, [turn off GraphiQL and introspection](https://strawberry.rocks/docs/operations/deployment), and add the [security extensions](https://strawberry.rocks/docs/operations/deployment#security-extensions) that limit query depth, aliases, and tokens. - -gRPC has you [define a service once in a `.proto` file](https://grpc.io/docs/languages/python/basics/) and generate its clients and servers in any language gRPC supports. Install `grpcio` and `grpcio-tools`, and [compile the `.proto` file into Python code with `grpc_tools.protoc`](https://grpc.io/docs/languages/python/quickstart/). [Use TLS](https://grpc.io/docs/guides/auth/) to authenticate the server and encrypt the traffic. - -Keep separate models for what an endpoint takes in and what it sends back. FastAPI [filters the response through the output model](https://fastapi.tiangolo.com/tutorial/response-model/#add-an-output-model), so fields the output model leaves out, like a password, never reach the client. APIFlask [recommends separate input and output schemas](https://apiflask.com/schema/#marshmallow) too. +gRPC lets you [define a service once in a `.proto` file](https://grpc.io/docs/languages/python/basics/) and generate clients and servers in any language it supports. For asyncio code, gRPC has [`grpc.aio`](https://grpc.github.io/grpc/python/grpc_asyncio.html).