Support for context sharing between parent and child types/fields
Feature Request Type
- [ ] Core functionality
- [ ] Alteration (enhancement/optimization) of existing feature(s)
- [x] New behavior
Description
In some cases it would be helpful if child objects/fields could access information about a parent object, especially for deeply nested types.
For example:
@strawberry.type
class User:
id: int
editor: bool
pages: List[Page]
@strawberry.type
class Page:
id: int
title: str
comments: List[Comment]
@strawberry.type
class Comment:
id: int
comment: str
@strawberry.field()
def can_edit(self) -> bool:
# get the user from current context, somehow
user = get_user_from_context()
if not user:
raise Exception("This field is only valid when queried under a User object")
return user.editor
@strawberry.type
class Query:
users: List[User]
pages: List[Page]
query {
users {
id
pages {
id
title
comments {
id
comment
canEdit
}
}
}
}
This can sort-of be achieved by storing information on info.context, but as far I can tell there isn't a safe way for this to be done for (at least) two reasons:
- In async context fields may not be resolved deterministically, so the information in info may or may not be valid for the current ancestor of the field
- There isn't a straightforward way, at least that I can see, to easily remove information from context after all fields in an object have been resolved
It would be nice if there was some sort of context available on info that could be automatically pushed/popped as fields are resolved, so that something like this could work as expected:
@strawberry.type
class User:
id: int
editor: bool
@strawberry.field()
def pages(self, info) -> List[Page]:
# user would be available to all descendants of User.pages, and be removed after User.pages completes
info.field_context.set('user', self)
return get_pages()
Another (admittedly, non DevX-friendly) workaround for this is to add a strawberry.Private field to the parent and also add it to all the children down the chain. That only works for certain use cases though, so I agree it would be great to have something else here.