Last active
November 6, 2019 13:56
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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