FastAPI-JSONAPI
  • Installation
  • A minimal API
  • Filtering API example
  • Quickstart
  • Limit API methods
  • Routing
  • Atomic Operations
  • View Dependencies
  • Filtering
  • Create and include related objects (updated example)
  • Include related objects
  • Include nested and related, Many-to-Many
    • Prepare models and schemas
      • Define SQLAlchemy models
        • Parent model
        • Child model
        • Parent to Child Association model
      • Define pydantic schemas
        • Parent Schema
        • Child Schema
        • Parent to Child Association Schema
      • Define view classes
        • Base Views
    • List Parent objects with Children through an Association object
  • Custom SQL filtering
  • Client generated id
  • Logical data abstraction
  • Data layer
  • Define relationships
  • Configuration
  • Sparse fieldsets
  • Pagination
  • Sorting
  • Errors
  • Permission
  • OAuth
  • Package fastapi_jsonapi index
  • Changelog
FastAPI-JSONAPI
  • Include nested and related, Many-to-Many
  • View page source

Include nested and related, Many-to-Many

The same as usual includes. Here’s an example with an association object.

Example (sources here):

Prepare models and schemas

Define SQLAlchemy models

Parent model

models/parent.py:

from sqlalchemy.orm import Mapped, relationship

from .base import Base
from .parent_to_child_association import ParentToChildAssociation


class Parent(Base):
    __tablename__ = "left_table_parents"

    name: Mapped[str]

    children: Mapped[list[ParentToChildAssociation]] = relationship(back_populates="parent", cascade="delete")

Child model

models/child.py:

from sqlalchemy.orm import Mapped, relationship

from .base import Base
from .parent_to_child_association import ParentToChildAssociation


class Child(Base):
    __tablename__ = "right_table_children"

    name: Mapped[str]

    parents: Mapped[list[ParentToChildAssociation]] = relationship(back_populates="child", cascade="delete")

Parent to Child Association model

models/parent_child_association.py:

Define pydantic schemas

Parent Schema

schemas/parent.py:

Child Schema

schemas/child.py:

Parent to Child Association Schema

schemas/parent_child_association.py:

Define view classes

Base Views

api/base.py:

from typing import ClassVar

from fastapi import Depends
from pydantic import BaseModel, ConfigDict
from sqlalchemy.engine import make_url
from sqlalchemy.ext.asyncio import AsyncSession

from examples.api_for_sqlalchemy import config
from examples.api_for_sqlalchemy.models.db import DB
from fastapi_jsonapi.data_layers.sqla.orm import SqlalchemyDataLayer
from fastapi_jsonapi.misc.sqla.generics.base import ViewBaseGeneric
from fastapi_jsonapi.views import Operation, OperationConfig, ViewBase

db = DB(
    url=make_url(config.SQLA_URI),
)


class SessionDependency(BaseModel):
    model_config = ConfigDict(
        arbitrary_types_allowed=True,
    )

    session: AsyncSession = Depends(db.session)


def handler(view: ViewBase, dto: SessionDependency) -> dict:
    return {
        "session": dto.session,
    }


class ViewBase(ViewBaseGeneric):
    """
    Generic view base (detail)
    """

    data_layer_cls = SqlalchemyDataLayer

    operation_dependencies: ClassVar = {
        Operation.ALL: OperationConfig(
            dependencies=SessionDependency,
            prepare_data_layer_kwargs=handler,
        ),
    }

List Parent objects with Children through an Association object

Request:

GET /parents?include=children%2Cchildren.child HTTP/1.1
Content-Type: application/vnd.api+json

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": [
    {
      "attributes": {
        "name": "parent_1"
      },
      "id": "1",
      "relationships": {
        "children": {
          "data": [
            {
              "id": "1",
              "type": "parent_child_association"
            },
            {
              "id": "3",
              "type": "parent_child_association"
            }
          ]
        }
      },
      "type": "parent"
    },
    {
      "attributes": {
        "name": "parent_2"
      },
      "id": "2",
      "relationships": {
        "children": {
          "data": [
            {
              "id": "2",
              "type": "parent_child_association"
            },
            {
              "id": "4",
              "type": "parent_child_association"
            },
            {
              "id": "5",
              "type": "parent_child_association"
            }
          ]
        }
      },
      "type": "parent"
    },
    {
      "attributes": {
        "name": "parent_3"
      },
      "id": "3",
      "relationships": {
        "children": {
          "data": []
        }
      },
      "type": "parent"
    }
  ],
  "included": [
    {
      "attributes": {
        "name": "child_1"
      },
      "id": "1",
      "type": "child"
    },
    {
      "attributes": {
        "name": "child_2"
      },
      "id": "2",
      "type": "child"
    },
    {
      "attributes": {
        "name": "child_3"
      },
      "id": "3",
      "type": "child"
    },
    {
      "attributes": {
        "extra_data": "assoc_p1c1_extra"
      },
      "id": "1",
      "relationships": {
        "child": {
          "data": {
            "id": "1",
            "type": "child"
          }
        }
      },
      "type": "parent_child_association"
    },
    {
      "attributes": {
        "extra_data": "assoc_p2c1_extra"
      },
      "id": "2",
      "relationships": {
        "child": {
          "data": {
            "id": "1",
            "type": "child"
          }
        }
      },
      "type": "parent_child_association"
    },
    {
      "attributes": {
        "extra_data": "assoc_p1c2_extra"
      },
      "id": "3",
      "relationships": {
        "child": {
          "data": {
            "id": "2",
            "type": "child"
          }
        }
      },
      "type": "parent_child_association"
    },
    {
      "attributes": {
        "extra_data": "assoc_p2c2_extra"
      },
      "id": "4",
      "relationships": {
        "child": {
          "data": {
            "id": "2",
            "type": "child"
          }
        }
      },
      "type": "parent_child_association"
    },
    {
      "attributes": {
        "extra_data": "assoc_p2c3_extra"
      },
      "id": "5",
      "relationships": {
        "child": {
          "data": {
            "id": "3",
            "type": "child"
          }
        }
      },
      "type": "parent_child_association"
    }
  ],
  "jsonapi": {
    "version": "1.0"
  },
  "meta": {
    "count": 3,
    "totalPages": 1
  }
}
Previous Next

© Copyright 2025, MTS AI.

Built with Sphinx using a theme provided by Read the Docs.