2

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"
      ]
     }
   ]
}
Cristoff
  • 149
  • 6
  • One solution would be `return Character(id=res['id'], name=res['name'], status=res['status'], species=res['species'])` and it works perfectly. But how can I do it differently if I have many fields? – Cristoff Nov 06 '22 at 13:43

1 Answers1

3

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)
patrick
  • 6,533
  • 7
  • 45
  • 66
  • So, this solution is a bad practice? – Cristoff Nov 19 '22 at 00:23
  • I think it is ok, as long as you know that this feature is enabled :) the issue with this is that you lose type checking for your resolvers, as mypy will complain ^^ – patrick Nov 19 '22 at 10:58