strawberry-graphql / strawberry

A GraphQL library for Python that leverages type annotations 🍓
https://strawberry.rocks
MIT License
4.01k stars 533 forks source link

Different contexts getters depending on the query or mutation #3347

Open Focadecombate opened 10 months ago

Focadecombate commented 10 months ago

Feature Request Type

Description

Currently the only way of doing context getters with fastapi integration is through multiple routers but then I would need to have different paths which I think would be weird in the graphql world. So I would like to be able of changing the context based on the resolver instead of setting only in the main router.

Upvote & Fund

Fund with Polar

patrick91 commented 10 months ago

changing the context based on the resolver instead of setting only in the main router.

do you have a more concrete example of this? 😊

Focadecombate commented 10 months ago

Something like this:

src.main.py

import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
from strawberry.tools import merge_types

from src.a import QueryA
from src.b import QueryB

app = FastAPI()

top_query = merge_types("AllQuery", (QueryB, QueryA))
main_schema = strawberry.Schema(top_query)
graphql_router = GraphQLRouter(schema=main_schema)

app.include_router(graphql_router, prefix="/graphql")

src.a.init.py

from typing import Any

import strawberry
from strawberry.fastapi import BaseContext
from strawberry.types import Info

class ServiceA:
    def hello_from_a(self):
        print("Hello from A")

class ContextA(BaseContext):
    def __init__(self, service: ServiceA) -> None:
        self.service = service

@strawberry.type
class QueryA:
    @strawberry.field
    def a(self, info: Info[ContextA, Any]) -> str:
        info.context.service.hello_from_a()
        return "a"

src.b.init.py

from typing import Any

import strawberry
from strawberry.fastapi import BaseContext
from strawberry.types import Info

class ServiceB:
    def hello_from_b(self):
        print("Hello from B")

class ContextB(BaseContext):
    def __init__(self, service: ServiceB) -> None:
        self.service = service

@strawberry.type
class QueryB:
    @strawberry.field
    def b(self, info: Info[ContextB, Any]) -> str:
        info.context.service.hello_from_b()
        return "b"