Accessing parentâs data in resolvers
It is quite common to want to be able to access the data from the fieldâs parent
in a resolver. For example letâs say that we want to define a fullName
field
on our User
. This would be our code:
In this case full_name
will need to access the first_name
and last_name
fields, and depending on whether we define the resolver as a function or as a
method, weâll have a few options! Letâs start with the defining a resolver as a
function.
Accessing parentâs data in function resolvers
Our resolver is a function with no arguments, in order to tell Strawberry to
pass us the parent of the field, we need to add a new argument with type
strawberry.Parent[ParentType]
, like so:
strawberry.Parent
tells Strawberry to pass the parent value of the field, in
this case it would be the User
.
Note:
strawberry.Parent
accepts a type argument, which will then be used by your type checker to check your code!
Using root
Historically Strawberry only supported passing the parent value by adding a
parameter called root
:
This is still supported, but we recommend using strawberry.Parent
, since it
follows Strawberryâs philosophy of using type annotations. Also, with
strawberry.Parent
your argument can have any name, for example this will still
work:
Accessing parentâs data in a method resolver
Both options also work when defining a method resolver, so we can still use
strawberry.Parent
in a resolver defined as a method:
But, hereâs where things get more interesting. If this was a pure Python class,
we would use self
directly, right? Turns out that Strawberry also supports
this!
Letâs update our resolver:
Much better, no? self
on resolver methods is pretty convenient, and it works
like it should in Python, but there might be cases where it doesnât properly
follow Pythonâs semantics. This is because under the hood resolvers are actually
called as if they were static methods by Strawberry.
Letâs see a simplified version of what happens when you request the full_name
field, to do that we also need a field that allows to fetch a user:
When we do a query like this:
We are pretty much asking to call the user
function on the Query
class, and
then call the full_name
function on the User
class, similar to this code:
While this might work for this case, it wonât work in other cases, like when returning a different type, for example when fetching the user from a database:
In this case our pseudo code would break, since UserModel
doesnât have a
full_name
function! But it does work when using Strawberry (provided that the
UserModel
has both first_name
and last_name
fields).
As mentioned, this is because Strawberry class the resolvers as if they were plain functions (not bound to the class), similar to this:
Youâre probably thinking of staticmethod
s and thatâs pretty much what we are
dealing with now! If you want to keep the resolver as a method on your class but
also want to remove some of the magic around self
, you can use the
@staticmethod
decorator in combination with strawberry.Parent
:
Combining @staticmethod
with strawberry.Parent
is a good way to make sure
that your code is clear and that you are aware of whatâs happening under the
hood, and it will keep your linters and type checkers happy!