From d972ef2cefb6ac25a1d78a2ee499073193bdaafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?= Date: Mon, 11 Mar 2019 20:26:36 +0100 Subject: [PATCH] Initial graphql endpoint. Only the program for now. --- src/bornhack/schema.py | 48 +++++++++++++++++ src/bornhack/settings.py | 5 +- src/bornhack/urls.py | 9 +++- src/program/schema.py | 95 +++++++++++++++++++++++++++++++++ src/requirements/production.txt | 2 + 5 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 src/bornhack/schema.py create mode 100644 src/program/schema.py diff --git a/src/bornhack/schema.py b/src/bornhack/schema.py new file mode 100644 index 00000000..106de42f --- /dev/null +++ b/src/bornhack/schema.py @@ -0,0 +1,48 @@ +from graphene import relay, Schema, ObjectType + +from graphene_django import DjangoObjectType +from graphene_django.filter import DjangoFilterConnectionField + +from camps.models import Camp + +from program.schema import ProgramQuery + + +class CampNode(DjangoObjectType): + class Meta: + model = Camp + interfaces = (relay.Node, ) + filter_fields = { + 'title': ['icontains', 'iexact'], + } + only_fields = ( + 'title', + 'slug', + 'tagline', + 'shortslug', + 'buildup', + 'camp', + 'teardown', + 'colour', + ) + + def resolve_buildup(self, info): + return [self.buildup.lower, self.buildup.upper] + + def resolve_camp(self, info): + return [self.camp.lower, self.camp.upper] + + def resolve_teardown(self, info): + return [self.teardown.lower, self.teardown.upper] + + +class CampQuery(object): + camp = relay.Node.Field(CampNode) + all_camps = DjangoFilterConnectionField(CampNode) + + +class Query(CampQuery, ProgramQuery, ObjectType): + pass + + +schema = Schema(query=Query) diff --git a/src/bornhack/settings.py b/src/bornhack/settings.py index cf3ca436..c7f6799c 100644 --- a/src/bornhack/settings.py +++ b/src/bornhack/settings.py @@ -43,6 +43,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'django.contrib.sites', + 'graphene_django', 'channels', 'profiles', @@ -190,4 +191,6 @@ LOGGING = { }, } - +GRAPHENE = { + 'SCHEMA': 'bornhack.schema.schema' +} diff --git a/src/bornhack/urls.py b/src/bornhack/urls.py index f9a10d44..a10b7ab7 100644 --- a/src/bornhack/urls.py +++ b/src/bornhack/urls.py @@ -1,9 +1,13 @@ +from django.urls import include, path +from django.contrib import admin +from django.conf import settings + from allauth.account.views import ( LoginView, LogoutView, ) -from django.urls import include, path -from django.contrib import admin +from graphene_django.views import GraphQLView + from camps.views import * from feedback.views import FeedbackCreate from info.views import * @@ -62,6 +66,7 @@ urlpatterns = [ ), path('accounts/', include('allauth.urls')), path('admin/', admin.site.urls), + path('api/', GraphQLView.as_view(graphiql=True)), path( 'camps/', diff --git a/src/program/schema.py b/src/program/schema.py new file mode 100644 index 00000000..54d93e39 --- /dev/null +++ b/src/program/schema.py @@ -0,0 +1,95 @@ +from graphene import relay + +from graphene_django import DjangoObjectType +from graphene_django.filter import DjangoFilterConnectionField + +from .models import ( + Event, + EventType, + EventLocation, + EventTrack, + EventInstance, + Speaker, +) + + +class EventTypeNode(DjangoObjectType): + class Meta: + model = EventType + interfaces = (relay.Node, ) + filter_fields = { + 'name': ['iexact'], + } + + +class EventLocationNode(DjangoObjectType): + class Meta: + model = EventLocation + interfaces = (relay.Node, ) + filter_fields = { + 'name': ['iexact'], + } + + +class EventTrackNode(DjangoObjectType): + class Meta: + model = EventTrack + interfaces = (relay.Node, ) + filter_fields = { + 'name': ['iexact'], + } + + +class EventInstanceNode(DjangoObjectType): + + class Meta: + model = EventInstance + interfaces = (relay.Node, ) + filter_fields = { + 'event__title': ['iexact'], + } + + def resolve_when(self, info): + # We need to resolve this ourselves, graphene-django isn't smart enough + return [self.when.lower, self.when.upper] + + +class SpeakerNode(DjangoObjectType): + class Meta: + model = Speaker + interfaces = (relay.Node, ) + only_fields = ('id', 'name', 'biography', 'slug', 'camp', 'events') + filter_fields = { + 'name': ['iexact'], + } + + +class EventNode(DjangoObjectType): + class Meta: + model = Event + interfaces = (relay.Node, ) + filter_fields = { + 'title': ['iexact'], + 'track__camp__slug': ['iexact'], + } + + +class ProgramQuery(object): + event_type = relay.Node.Field(EventTypeNode) + all_event_types = DjangoFilterConnectionField(EventTypeNode) + + event_location = relay.Node.Field(EventLocationNode) + all_event_locations = DjangoFilterConnectionField(EventLocationNode) + + event_track = relay.Node.Field(EventTrackNode) + all_event_tracks = DjangoFilterConnectionField(EventTrackNode) + + event_instance = relay.Node.Field(EventInstanceNode) + all_event_instances = DjangoFilterConnectionField(EventInstanceNode) + + event = relay.Node.Field(EventNode) + all_events = DjangoFilterConnectionField(EventNode) + + speaker = relay.Node.Field(SpeakerNode) + all_speakers = DjangoFilterConnectionField(SpeakerNode) + diff --git a/src/requirements/production.txt b/src/requirements/production.txt index 12484597..31f3a5a9 100644 --- a/src/requirements/production.txt +++ b/src/requirements/production.txt @@ -36,4 +36,6 @@ sqlparse==0.2.4 venusian==1.2.0 webencodings==0.5.1 wrapt==1.11.1 +graphene-django==2.2.0 +django-filter==2.1.0