import graphene from wagtail.models import Page from books.models import Module, Topic from books.schema.nodes import ModuleNode from graphene import relay from graphene_django import DjangoObjectType from graphene_django.filter import DjangoFilterConnectionField from notes.models import Highlight class NotFoundFailure: reason = "Not Found" class NotFound(graphene.ObjectType): reason = graphene.String() class TopicNode(DjangoObjectType): pk = graphene.Int() modules = graphene.List(graphene.NonNull("books.schema.nodes.ModuleNode")) highlights = graphene.List("notes.schema.HighlightNode") class Meta: model = Topic only_fields = [ "slug", "title", "teaser", "description", "vimeo_id", "order", "instructions", ] filter_fields = { "slug": ["exact", "icontains", "in"], "title": ["exact", "icontains", "in"], } interfaces = (relay.Node,) def resolve_pk(self, *args, **kwargs): return self.id def resolve_modules(self, *args, **kwargs): translations = self.get_translations() ids = list(self.get_child_ids()) for translation in translations: ids += list(translation.get_child_ids()) return Module.objects.filter(id__in=ids).live() @staticmethod def resolve_highlights(root: Topic, info, **kwargs): # todo: is this too expensive, query-wise? pages = Page.objects.live().descendant_of(root) return Highlight.objects.filter(user=info.context.user).filter(page__in=pages) class TopicOr404Node(graphene.Union): class Meta: types = (TopicNode, NotFound) @classmethod def resolve_type(cls, instance, info): if type(instance).__name__ == "Topic": return TopicNode return NotFound