Skip to content

Instantly share code, notes, and snippets.

@patrys
Last active November 6, 2019 13:56
Show Gist options
  • Save patrys/88ec30ed14650ebae15156fe3c5e8afa to your computer and use it in GitHub Desktop.
Save patrys/88ec30ed14650ebae15156fe3c5e8afa to your computer and use it in GitHub Desktop.
An ugly hack that allows type composition in Graphene, as it depends on metaclasses, you need to explicitly import the extension for it to work
from .extensions import ObjectTypeExtension
class OrderWithEvents(ObjectTypeExtension):
class Meta:
base_type = Order
events = graphene.Field(
graphene.List(
OrderEvent, description="List of events associated with the order."
)
)
@staticmethod
def resolve_events(root: models.Order, _info):
return root.events.all().order_by("pk")
from collections import OrderedDict
from graphene import Field, Interface
from graphene.utils.subclass_with_meta import SubclassWithMeta
from graphene.types.utils import yank_fields_from_attrs
class ObjectTypeExtension(SubclassWithMeta):
@classmethod
def __init_subclass_with_meta__(cls, interfaces=(), **options):
fields = OrderedDict()
object_type = options["base_type"]
object_meta = object_type._meta
for interface in interfaces:
assert issubclass(interface, Interface), (
'All interfaces of {} must be a subclass of Interface. Received "{}".'
).format(cls.__name__, interface)
fields.update(interface._meta.fields)
for base in reversed(cls.__mro__):
fields.update(yank_fields_from_attrs(base.__dict__, _as=Field))
for field_name in fields.keys():
resolver_name = f"resolve_{field_name}"
resolver_func = getattr(cls, resolver_name, None)
if resolver_func:
setattr(object_type, resolver_name, resolver_func)
object_meta.fields.update(fields)
super().__init_subclass_with_meta__(**options)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment