From 5ef8c07f306158fac8be77515889cc2eeabb6dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Sat, 18 Nov 2023 21:09:27 +0100 Subject: [PATCH 1/7] Initial working API --- games/schema.py | 82 +++++++++++++++++++++++++++++ poetry.lock | 112 +++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + tests/test_graphql.py | 35 +++++++++++++ timetracker/settings.py | 3 ++ timetracker/urls.py | 3 ++ 6 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 games/schema.py create mode 100644 tests/test_graphql.py diff --git a/games/schema.py b/games/schema.py new file mode 100644 index 0000000..a5d2908 --- /dev/null +++ b/games/schema.py @@ -0,0 +1,82 @@ +import graphene +from graphene_django import DjangoObjectType + +from .models import Device as DeviceModel +from .models import Edition as EditionModel +from .models import Game as GameModel +from .models import Platform as PlatformModel +from .models import Purchase as PurchaseModel +from .models import Session as SessionModel + + +class Game(DjangoObjectType): + class Meta: + model = GameModel + fields = "__all__" + + +class Edition(DjangoObjectType): + class Meta: + model = EditionModel + fields = "__all__" + + +class Purchase(DjangoObjectType): + class Meta: + model = PurchaseModel + fields = "__all__" + + +class Session(DjangoObjectType): + class Meta: + model = SessionModel + fields = "__all__" + + +class Platform(DjangoObjectType): + class Meta: + model = PlatformModel + fields = "__all__" + + +class Device(DjangoObjectType): + class Meta: + model = DeviceModel + fields = "__all__" + + +class Query(graphene.ObjectType): + games = graphene.List(Game) + game_by_name = graphene.Field(Game, name=graphene.String(required=True)) + purchases = graphene.List(Purchase) + editions = graphene.List(Edition) + sessions = graphene.List(Session) + platforms = graphene.List(Platform) + devices = graphene.List(Device) + + def resolve_games(self, info, **kwargs): + return GameModel.objects.all() + + def resolve_game_by_name(self, info, name): + try: + return GameModel.objects.get(name=name) + except GameModel.DoesNotExist: + return None + + def resolve_editions(self, info, **kwargs): + return EditionModel.objects.all() + + def resolve_purchases(self, info, **kwargs): + return PurchaseModel.objects.all() + + def resolve_sessions(self, info, **kwargs): + return SessionModel.objects.all() + + def resolve_platforms(self, info, **kwargs): + return PlatformModel.objects.all() + + def resolve_devices(self, info, **kwargs): + return DeviceModel.objects.all() + + +schema = graphene.Schema(query=Query) diff --git a/poetry.lock b/poetry.lock index 7afd4c3..e4a8df0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,19 @@ # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +[[package]] +name = "aniso8601" +version = "9.0.1" +description = "A library for parsing ISO 8601 strings." +optional = false +python-versions = "*" +files = [ + {file = "aniso8601-9.0.1-py2.py3-none-any.whl", hash = "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f"}, + {file = "aniso8601-9.0.1.tar.gz", hash = "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"}, +] + +[package.extras] +dev = ["black", "coverage", "isort", "pre-commit", "pyenchant", "pylint"] + [[package]] name = "asgiref" version = "3.7.2" @@ -222,6 +236,75 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] +[[package]] +name = "graphene" +version = "3.3" +description = "GraphQL Framework for Python" +optional = false +python-versions = "*" +files = [ + {file = "graphene-3.3-py2.py3-none-any.whl", hash = "sha256:bb3810be33b54cb3e6969506671eb72319e8d7ba0d5ca9c8066472f75bf35a38"}, + {file = "graphene-3.3.tar.gz", hash = "sha256:529bf40c2a698954217d3713c6041d69d3f719ad0080857d7ee31327112446b0"}, +] + +[package.dependencies] +aniso8601 = ">=8,<10" +graphql-core = ">=3.1,<3.3" +graphql-relay = ">=3.1,<3.3" + +[package.extras] +dev = ["black (==22.3.0)", "coveralls (>=3.3,<4)", "flake8 (>=4,<5)", "iso8601 (>=1,<2)", "mock (>=4,<5)", "pytest (>=6,<7)", "pytest-asyncio (>=0.16,<2)", "pytest-benchmark (>=3.4,<4)", "pytest-cov (>=3,<4)", "pytest-mock (>=3,<4)", "pytz (==2022.1)", "snapshottest (>=0.6,<1)"] +test = ["coveralls (>=3.3,<4)", "iso8601 (>=1,<2)", "mock (>=4,<5)", "pytest (>=6,<7)", "pytest-asyncio (>=0.16,<2)", "pytest-benchmark (>=3.4,<4)", "pytest-cov (>=3,<4)", "pytest-mock (>=3,<4)", "pytz (==2022.1)", "snapshottest (>=0.6,<1)"] + +[[package]] +name = "graphene-django" +version = "3.1.5" +description = "Graphene Django integration" +optional = false +python-versions = "*" +files = [ + {file = "graphene-django-3.1.5.tar.gz", hash = "sha256:abe42f820b9731d94bebff6d73088d0dc2ffb8c8863a6d7bf3d378412d866a3b"}, + {file = "graphene_django-3.1.5-py2.py3-none-any.whl", hash = "sha256:2e42742fae21fa50e514f3acae26a9bc6cb5e51c179a97b3db5390ff258ca816"}, +] + +[package.dependencies] +Django = ">=3.2" +graphene = ">=3.0,<4" +graphql-core = ">=3.1.0,<4" +graphql-relay = ">=3.1.1,<4" +promise = ">=2.1" +text-unidecode = "*" + +[package.extras] +dev = ["black (==23.7.0)", "coveralls", "django-filter (>=22.1)", "djangorestframework (>=3.6.3)", "mock", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-django (>=4.5.2)", "pytest-random-order", "pytz", "ruff (==0.0.283)"] +rest-framework = ["djangorestframework (>=3.6.3)"] +test = ["coveralls", "django-filter (>=22.1)", "djangorestframework (>=3.6.3)", "mock", "pytest (>=7.3.1)", "pytest-cov", "pytest-django (>=4.5.2)", "pytest-random-order", "pytz"] + +[[package]] +name = "graphql-core" +version = "3.2.3" +description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "graphql-core-3.2.3.tar.gz", hash = "sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676"}, + {file = "graphql_core-3.2.3-py3-none-any.whl", hash = "sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3"}, +] + +[[package]] +name = "graphql-relay" +version = "3.2.0" +description = "Relay library for graphql-core" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "graphql-relay-3.2.0.tar.gz", hash = "sha256:1ff1c51298356e481a0be009ccdff249832ce53f30559c1338f22a0e0d17250c"}, + {file = "graphql_relay-3.2.0-py3-none-any.whl", hash = "sha256:c9b22bd28b170ba1fe674c74384a8ff30a76c8e26f88ac3aa1584dd3179953e5"}, +] + +[package.dependencies] +graphql-core = ">=3.2,<3.3" + [[package]] name = "gunicorn" version = "20.1.0" @@ -558,6 +641,22 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "promise" +version = "2.3" +description = "Promises/A+ implementation for Python" +optional = false +python-versions = "*" +files = [ + {file = "promise-2.3.tar.gz", hash = "sha256:dfd18337c523ba4b6a58801c164c1904a9d4d1b1747c7d5dbf45b693a49d93d0"}, +] + +[package.dependencies] +six = "*" + +[package.extras] +test = ["coveralls", "futures", "mock", "pytest (>=2.7.3)", "pytest-benchmark", "pytest-cov"] + [[package]] name = "pytest" version = "7.4.3" @@ -777,6 +876,17 @@ dev = ["build", "flake8"] doc = ["sphinx"] test = ["pytest", "pytest-cov"] +[[package]] +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +optional = false +python-versions = "*" +files = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] + [[package]] name = "tqdm" version = "4.66.1" @@ -877,4 +987,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "498b3358998a9f3bbfb74fae7d6a90de7b55b9bdc76845bce52f65785afd0c1e" +content-hash = "49b33333953d875c6c2a26ffd1a1a2d21f75e06fe59e6619ba2900e39d2cf1bf" diff --git a/pyproject.toml b/pyproject.toml index e13ac5a..d17eda8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ python = "^3.12" django = "^4.2.0" gunicorn = "^20.1.0" uvicorn = "^0.20.0" +graphene-django = "^3.1.5" [tool.poetry.group.dev.dependencies] black = "^22.12.0" diff --git a/tests/test_graphql.py b/tests/test_graphql.py new file mode 100644 index 0000000..24471a8 --- /dev/null +++ b/tests/test_graphql.py @@ -0,0 +1,35 @@ +import json +import os + +import django + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "timetracker.settings") +django.setup() + +from django.test import TestCase +from graphene_django.utils.testing import GraphQLTestCase + +from games import schema +from games.models import Game + + +class GameAPITestCase(GraphQLTestCase): + GRAPHENE_SCHEMA = schema.schema + + def test_query_all_games(self): + response = self.query( + """ + query { + games { + id + name + } + } + """ + ) + + self.assertResponseNoErrors(response) + self.assertEqual( + len(json.loads(response.content)["data"]["games"]), + Game.objects.count(), + ) diff --git a/timetracker/settings.py b/timetracker/settings.py index 7238b9b..6386976 100644 --- a/timetracker/settings.py +++ b/timetracker/settings.py @@ -38,8 +38,11 @@ INSTALLED_APPS = [ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "graphene_django", ] +GRAPHENE = {"SCHEMA": "games.schema.schema"} + if DEBUG: INSTALLED_APPS.append("django_extensions") INSTALLED_APPS.append("django.contrib.admin") diff --git a/timetracker/urls.py b/timetracker/urls.py index 0515e99..3f91c05 100644 --- a/timetracker/urls.py +++ b/timetracker/urls.py @@ -16,11 +16,14 @@ Including another URLconf from django.conf import settings from django.contrib import admin from django.urls import include, path +from django.views.decorators.csrf import csrf_exempt from django.views.generic import RedirectView +from graphene_django.views import GraphQLView urlpatterns = [ path("", RedirectView.as_view(url="/tracker")), path("tracker/", include("games.urls")), + path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))), ] if settings.DEBUG: -- 2.40.1 From cb380814a754ab7e9c7dbb25a3258b98432120dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 29 Nov 2023 21:04:35 +0100 Subject: [PATCH 2/7] Move GraphQL to separata app --- api/__init__.py | 0 api/admin.py | 3 +++ api/apps.py | 6 ++++++ api/migrations/__init__.py | 0 api/models.py | 3 +++ {games => api}/schema.py | 12 ++++++------ api/tests.py | 3 +++ api/views.py | 3 +++ timetracker/settings.py | 3 ++- 9 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 api/__init__.py create mode 100644 api/admin.py create mode 100644 api/apps.py create mode 100644 api/migrations/__init__.py create mode 100644 api/models.py rename {games => api}/schema.py (86%) create mode 100644 api/tests.py create mode 100644 api/views.py diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/admin.py b/api/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/api/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/api/apps.py b/api/apps.py new file mode 100644 index 0000000..878e7d5 --- /dev/null +++ b/api/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "api" diff --git a/api/migrations/__init__.py b/api/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/models.py b/api/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/api/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/games/schema.py b/api/schema.py similarity index 86% rename from games/schema.py rename to api/schema.py index a5d2908..98f3860 100644 --- a/games/schema.py +++ b/api/schema.py @@ -1,12 +1,12 @@ import graphene from graphene_django import DjangoObjectType -from .models import Device as DeviceModel -from .models import Edition as EditionModel -from .models import Game as GameModel -from .models import Platform as PlatformModel -from .models import Purchase as PurchaseModel -from .models import Session as SessionModel +from games.models import Device as DeviceModel +from games.models import Edition as EditionModel +from games.models import Game as GameModel +from games.models import Platform as PlatformModel +from games.models import Purchase as PurchaseModel +from games.models import Session as SessionModel class Game(DjangoObjectType): diff --git a/api/tests.py b/api/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/api/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/api/views.py b/api/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/api/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/timetracker/settings.py b/timetracker/settings.py index 6386976..47e5e21 100644 --- a/timetracker/settings.py +++ b/timetracker/settings.py @@ -33,6 +33,7 @@ ALLOWED_HOSTS = ["*"] INSTALLED_APPS = [ "games.apps.GamesConfig", + "api.apps.ApiConfig", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", @@ -41,7 +42,7 @@ INSTALLED_APPS = [ "graphene_django", ] -GRAPHENE = {"SCHEMA": "games.schema.schema"} +GRAPHENE = {"SCHEMA": "api.schema.schema"} if DEBUG: INSTALLED_APPS.append("django_extensions") -- 2.40.1 From 52513e1ed8e55feb65396a55f5b043d9957b42fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 29 Nov 2023 21:05:34 +0100 Subject: [PATCH 3/7] Add UpdateGameMutation --- api/schema.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/api/schema.py b/api/schema.py index 98f3860..c359e08 100644 --- a/api/schema.py +++ b/api/schema.py @@ -15,6 +15,27 @@ class Game(DjangoObjectType): fields = "__all__" +class UpdateGameMutation(graphene.Mutation): + class Arguments: + id = graphene.ID(required=True) + name = graphene.String() + year_released = graphene.Int() + wikidata = graphene.String() + + game = graphene.Field(Game) + + def mutate(self, info, id, name=None, year_released=None, wikidata=None): + game_instance = GameModel.objects.get(pk=id) + if name is not None: + game_instance.name = name + if year_released is not None: + game_instance.year_released = year_released + if wikidata is not None: + game_instance.wikidata = wikidata + game_instance.save() + return UpdateGameMutation(game=game_instance) + + class Edition(DjangoObjectType): class Meta: model = EditionModel @@ -79,4 +100,8 @@ class Query(graphene.ObjectType): return DeviceModel.objects.all() -schema = graphene.Schema(query=Query) +class Mutation(graphene.ObjectType): + update_game = UpdateGameMutation.Field() + + +schema = graphene.Schema(query=Query, mutation=Mutation) -- 2.40.1 From d921c2d8a6eab228fb9ba274cfdd9f36983fbcb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 29 Nov 2023 21:17:41 +0100 Subject: [PATCH 4/7] Revert "Add UpdateGameMutation" This reverts commit e9e61403a9f3c93f02bf1c3ffd86a40c68954c55. --- api/schema.py | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/api/schema.py b/api/schema.py index c359e08..98f3860 100644 --- a/api/schema.py +++ b/api/schema.py @@ -15,27 +15,6 @@ class Game(DjangoObjectType): fields = "__all__" -class UpdateGameMutation(graphene.Mutation): - class Arguments: - id = graphene.ID(required=True) - name = graphene.String() - year_released = graphene.Int() - wikidata = graphene.String() - - game = graphene.Field(Game) - - def mutate(self, info, id, name=None, year_released=None, wikidata=None): - game_instance = GameModel.objects.get(pk=id) - if name is not None: - game_instance.name = name - if year_released is not None: - game_instance.year_released = year_released - if wikidata is not None: - game_instance.wikidata = wikidata - game_instance.save() - return UpdateGameMutation(game=game_instance) - - class Edition(DjangoObjectType): class Meta: model = EditionModel @@ -100,8 +79,4 @@ class Query(graphene.ObjectType): return DeviceModel.objects.all() -class Mutation(graphene.ObjectType): - update_game = UpdateGameMutation.Field() - - -schema = graphene.Schema(query=Query, mutation=Mutation) +schema = graphene.Schema(query=Query) -- 2.40.1 From d1c3ac607974504ee4c956ea8e0f882dcad5ac79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 29 Nov 2023 21:18:02 +0100 Subject: [PATCH 5/7] Revert "Move GraphQL to separata app" This reverts commit 6ac4209492c95e7fc06b6a7ba9fced42d42037b8. --- api/__init__.py | 0 api/admin.py | 3 --- api/apps.py | 6 ------ api/migrations/__init__.py | 0 api/models.py | 3 --- api/tests.py | 3 --- api/views.py | 3 --- {api => games}/schema.py | 12 ++++++------ timetracker/settings.py | 3 +-- 9 files changed, 7 insertions(+), 26 deletions(-) delete mode 100644 api/__init__.py delete mode 100644 api/admin.py delete mode 100644 api/apps.py delete mode 100644 api/migrations/__init__.py delete mode 100644 api/models.py delete mode 100644 api/tests.py delete mode 100644 api/views.py rename {api => games}/schema.py (86%) diff --git a/api/__init__.py b/api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/api/admin.py b/api/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/api/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/api/apps.py b/api/apps.py deleted file mode 100644 index 878e7d5..0000000 --- a/api/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class ApiConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "api" diff --git a/api/migrations/__init__.py b/api/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/api/models.py b/api/models.py deleted file mode 100644 index 71a8362..0000000 --- a/api/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/api/tests.py b/api/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/api/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/api/views.py b/api/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/api/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/api/schema.py b/games/schema.py similarity index 86% rename from api/schema.py rename to games/schema.py index 98f3860..a5d2908 100644 --- a/api/schema.py +++ b/games/schema.py @@ -1,12 +1,12 @@ import graphene from graphene_django import DjangoObjectType -from games.models import Device as DeviceModel -from games.models import Edition as EditionModel -from games.models import Game as GameModel -from games.models import Platform as PlatformModel -from games.models import Purchase as PurchaseModel -from games.models import Session as SessionModel +from .models import Device as DeviceModel +from .models import Edition as EditionModel +from .models import Game as GameModel +from .models import Platform as PlatformModel +from .models import Purchase as PurchaseModel +from .models import Session as SessionModel class Game(DjangoObjectType): diff --git a/timetracker/settings.py b/timetracker/settings.py index 47e5e21..6386976 100644 --- a/timetracker/settings.py +++ b/timetracker/settings.py @@ -33,7 +33,6 @@ ALLOWED_HOSTS = ["*"] INSTALLED_APPS = [ "games.apps.GamesConfig", - "api.apps.ApiConfig", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", @@ -42,7 +41,7 @@ INSTALLED_APPS = [ "graphene_django", ] -GRAPHENE = {"SCHEMA": "api.schema.schema"} +GRAPHENE = {"SCHEMA": "games.schema.schema"} if DEBUG: INSTALLED_APPS.append("django_extensions") -- 2.40.1 From fde93cb8754969c5183975a3717145542bbab755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 29 Nov 2023 21:58:33 +0100 Subject: [PATCH 6/7] Organize better --- games/graphql/mutations/__init__.py | 1 + games/graphql/mutations/game.py | 29 +++++++++ games/graphql/queries/__init__.py | 6 ++ games/graphql/queries/device.py | 11 ++++ games/graphql/queries/edition.py | 11 ++++ games/graphql/queries/game.py | 18 ++++++ games/graphql/queries/platform.py | 11 ++++ games/graphql/queries/purchase.py | 11 ++++ games/graphql/queries/session.py | 11 ++++ games/graphql/types.py | 44 +++++++++++++ games/schema.py | 96 +++++++---------------------- 11 files changed, 175 insertions(+), 74 deletions(-) create mode 100644 games/graphql/mutations/__init__.py create mode 100644 games/graphql/mutations/game.py create mode 100644 games/graphql/queries/__init__.py create mode 100644 games/graphql/queries/device.py create mode 100644 games/graphql/queries/edition.py create mode 100644 games/graphql/queries/game.py create mode 100644 games/graphql/queries/platform.py create mode 100644 games/graphql/queries/purchase.py create mode 100644 games/graphql/queries/session.py create mode 100644 games/graphql/types.py diff --git a/games/graphql/mutations/__init__.py b/games/graphql/mutations/__init__.py new file mode 100644 index 0000000..c44e61a --- /dev/null +++ b/games/graphql/mutations/__init__.py @@ -0,0 +1 @@ +from .game import Mutation as GameMutation diff --git a/games/graphql/mutations/game.py b/games/graphql/mutations/game.py new file mode 100644 index 0000000..c298606 --- /dev/null +++ b/games/graphql/mutations/game.py @@ -0,0 +1,29 @@ +import graphene + +from games.graphql.types import Game +from games.models import Game as GameModel + + +class UpdateGameMutation(graphene.Mutation): + class Arguments: + id = graphene.ID(required=True) + name = graphene.String() + year_released = graphene.Int() + wikidata = graphene.String() + + game = graphene.Field(Game) + + def mutate(self, info, id, name=None, year_released=None, wikidata=None): + game_instance = GameModel.objects.get(pk=id) + if name is not None: + game_instance.name = name + if year_released is not None: + game_instance.year_released = year_released + if wikidata is not None: + game_instance.wikidata = wikidata + game_instance.save() + return UpdateGameMutation(game=game_instance) + + +class Mutation(graphene.ObjectType): + update_game = UpdateGameMutation.Field() diff --git a/games/graphql/queries/__init__.py b/games/graphql/queries/__init__.py new file mode 100644 index 0000000..7eb49a9 --- /dev/null +++ b/games/graphql/queries/__init__.py @@ -0,0 +1,6 @@ +from .device import Query as DeviceQuery +from .edition import Query as EditionQuery +from .game import Query as GameQuery +from .platform import Query as PlatformQuery +from .purchase import Query as PurchaseQuery +from .session import Query as SessionQuery diff --git a/games/graphql/queries/device.py b/games/graphql/queries/device.py new file mode 100644 index 0000000..19657eb --- /dev/null +++ b/games/graphql/queries/device.py @@ -0,0 +1,11 @@ +import graphene + +from games.graphql.types import Device +from games.models import Device as DeviceModel + + +class Query(graphene.ObjectType): + devices = graphene.List(Device) + + def resolve_devices(self, info, **kwargs): + return DeviceModel.objects.all() diff --git a/games/graphql/queries/edition.py b/games/graphql/queries/edition.py new file mode 100644 index 0000000..63a2492 --- /dev/null +++ b/games/graphql/queries/edition.py @@ -0,0 +1,11 @@ +import graphene + +from games.graphql.types import Edition +from games.models import Game as EditionModel + + +class Query(graphene.ObjectType): + editions = graphene.List(Edition) + + def resolve_editions(self, info, **kwargs): + return EditionModel.objects.all() diff --git a/games/graphql/queries/game.py b/games/graphql/queries/game.py new file mode 100644 index 0000000..0c74173 --- /dev/null +++ b/games/graphql/queries/game.py @@ -0,0 +1,18 @@ +import graphene + +from games.graphql.types import Game +from games.models import Game as GameModel + + +class Query(graphene.ObjectType): + games = graphene.List(Game) + game_by_name = graphene.Field(Game, name=graphene.String(required=True)) + + def resolve_games(self, info, **kwargs): + return GameModel.objects.all() + + def resolve_game_by_name(self, info, name): + try: + return GameModel.objects.get(name=name) + except GameModel.DoesNotExist: + return None diff --git a/games/graphql/queries/platform.py b/games/graphql/queries/platform.py new file mode 100644 index 0000000..44226b3 --- /dev/null +++ b/games/graphql/queries/platform.py @@ -0,0 +1,11 @@ +import graphene + +from games.graphql.types import Platform +from games.models import Platform as PlatformModel + + +class Query(graphene.ObjectType): + platforms = graphene.List(Platform) + + def resolve_platforms(self, info, **kwargs): + return PlatformModel.objects.all() diff --git a/games/graphql/queries/purchase.py b/games/graphql/queries/purchase.py new file mode 100644 index 0000000..e54e0d5 --- /dev/null +++ b/games/graphql/queries/purchase.py @@ -0,0 +1,11 @@ +import graphene + +from games.graphql.types import Purchase +from games.models import Purchase as PurchaseModel + + +class Query(graphene.ObjectType): + purchases = graphene.List(Purchase) + + def resolve_purchases(self, info, **kwargs): + return PurchaseModel.objects.all() diff --git a/games/graphql/queries/session.py b/games/graphql/queries/session.py new file mode 100644 index 0000000..42afbf1 --- /dev/null +++ b/games/graphql/queries/session.py @@ -0,0 +1,11 @@ +import graphene + +from games.graphql.types import Session +from games.models import Session as SessionModel + + +class Query(graphene.ObjectType): + sessions = graphene.List(Session) + + def resolve_sessions(self, info, **kwargs): + return SessionModel.objects.all() diff --git a/games/graphql/types.py b/games/graphql/types.py new file mode 100644 index 0000000..4d2de17 --- /dev/null +++ b/games/graphql/types.py @@ -0,0 +1,44 @@ +from graphene_django import DjangoObjectType + +from games.models import Device as DeviceModel +from games.models import Edition as EditionModel +from games.models import Game as GameModel +from games.models import Platform as PlatformModel +from games.models import Purchase as PurchaseModel +from games.models import Session as SessionModel + + +class Game(DjangoObjectType): + class Meta: + model = GameModel + fields = "__all__" + + +class Edition(DjangoObjectType): + class Meta: + model = EditionModel + fields = "__all__" + + +class Purchase(DjangoObjectType): + class Meta: + model = PurchaseModel + fields = "__all__" + + +class Session(DjangoObjectType): + class Meta: + model = SessionModel + fields = "__all__" + + +class Platform(DjangoObjectType): + class Meta: + model = PlatformModel + fields = "__all__" + + +class Device(DjangoObjectType): + class Meta: + model = DeviceModel + fields = "__all__" diff --git a/games/schema.py b/games/schema.py index a5d2908..96d2239 100644 --- a/games/schema.py +++ b/games/schema.py @@ -1,82 +1,30 @@ import graphene -from graphene_django import DjangoObjectType -from .models import Device as DeviceModel -from .models import Edition as EditionModel -from .models import Game as GameModel -from .models import Platform as PlatformModel -from .models import Purchase as PurchaseModel -from .models import Session as SessionModel +from games.graphql.mutations import GameMutation +from games.graphql.queries import ( + DeviceQuery, + EditionQuery, + GameQuery, + PlatformQuery, + PurchaseQuery, + SessionQuery, +) -class Game(DjangoObjectType): - class Meta: - model = GameModel - fields = "__all__" +class Query( + GameQuery, + EditionQuery, + DeviceQuery, + PlatformQuery, + PurchaseQuery, + SessionQuery, + graphene.ObjectType, +): + pass -class Edition(DjangoObjectType): - class Meta: - model = EditionModel - fields = "__all__" +class Mutation(GameMutation, graphene.ObjectType): + pass -class Purchase(DjangoObjectType): - class Meta: - model = PurchaseModel - fields = "__all__" - - -class Session(DjangoObjectType): - class Meta: - model = SessionModel - fields = "__all__" - - -class Platform(DjangoObjectType): - class Meta: - model = PlatformModel - fields = "__all__" - - -class Device(DjangoObjectType): - class Meta: - model = DeviceModel - fields = "__all__" - - -class Query(graphene.ObjectType): - games = graphene.List(Game) - game_by_name = graphene.Field(Game, name=graphene.String(required=True)) - purchases = graphene.List(Purchase) - editions = graphene.List(Edition) - sessions = graphene.List(Session) - platforms = graphene.List(Platform) - devices = graphene.List(Device) - - def resolve_games(self, info, **kwargs): - return GameModel.objects.all() - - def resolve_game_by_name(self, info, name): - try: - return GameModel.objects.get(name=name) - except GameModel.DoesNotExist: - return None - - def resolve_editions(self, info, **kwargs): - return EditionModel.objects.all() - - def resolve_purchases(self, info, **kwargs): - return PurchaseModel.objects.all() - - def resolve_sessions(self, info, **kwargs): - return SessionModel.objects.all() - - def resolve_platforms(self, info, **kwargs): - return PlatformModel.objects.all() - - def resolve_devices(self, info, **kwargs): - return DeviceModel.objects.all() - - -schema = graphene.Schema(query=Query) +schema = graphene.Schema(query=Query, mutation=Mutation) -- 2.40.1 From d1b9202337931aad8bb32fb7308df2a8bf684b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 29 Nov 2023 22:21:27 +0100 Subject: [PATCH 7/7] Update poetry.lock --- .gitignore | 4 ++-- poetry.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5870995..1849b79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ __pycache__ .mypy_cache .pytest_cache -.venv +.venv/ node_modules package-lock.json db.sqlite3 /static/ -dist/ \ No newline at end of file +dist/ diff --git a/poetry.lock b/poetry.lock index e4a8df0..07940fa 100644 --- a/poetry.lock +++ b/poetry.lock @@ -987,4 +987,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "49b33333953d875c6c2a26ffd1a1a2d21f75e06fe59e6619ba2900e39d2cf1bf" +content-hash = "e864dc8abf6c84e5bb16ac2aa937c2a70561d15f3e8a1459866b9d6507e8773e" -- 2.40.1