Search code examples
pythonpython-requestsgraphqlfastapistrawberry-graphql

Fastapi with strawberry is returning Error "'dict' object has no attribute 'name'"


I am trying to get character fields from the api rest of Rick&Morty using graphql with Fastapi + StrawBerry and i always get the same error with the first field i write

my code:

from fastapi import FastAPI
import strawberry
from strawberry.fastapi import GraphQLRouter
import requests

@strawberry.type
class Character:
    id: int
    name: str
    status: str
    species: str

@strawberry.type
class Query:
    @strawberry.field
    def getIdent(self, ch: str) -> Character:
        url = f'https://rickandmortyapi.com/api/character/{ch}'
        return requests.get(url).json()

app = FastAPI()
schema = strawberry.Schema(Query)
graphql_app = GraphQLRouter(schema)
app.include_router(graphql_app, prefix="/graphql")

my graphql query:

query MyQuery {
  getIdent(ch: "2") {
    name
    species
  }
}

and the error:

{
   "data": null,
   "errors": [
     {
       "message": "'dict' object has no attribute 'name'",
       "locations": [
          {
            "line": 3,
            "column": 5
          }
      ],
        "path": [
        "getIdent",
        "name"
      ]
     }
   ]
}

Solution

  • Strawberry doesn't allow returning dictionaries by default, this is done to keep the type safety of your code, but there's a configuration option that allow you to do this. Using StrawberryConfig and a custom default resolver you can allow returning both dictionaries and instances, see this example:

    https://play.strawberry.rocks/?gist=c788907c4421b55d3cb077431fe3b6c7

    Relevant code here:

    # a custom default resolver that tries to use getitem 
    # to get the return value, otherwise it fallbacks to 
    # the default behaviour, which is getattr
    def default_resolver(root, field):
        try:
            return operator.getitem(root, field)
        except KeyError:
            return getattr(root, field)
    
    config = StrawberryConfig(
        default_resolver=default_resolver
    )
    
    schema = strawberry.Schema(query=Query, config=config)