diff --git a/.gitignore b/.gitignore index 40744a4..057a9f0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ db-sources hhub/migrations __pycache__ *.sqlite3 +# The schema is autogenerated +schema.yml diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 751679a..30a9b19 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -23,6 +23,10 @@ until postgres_ready; do case "$1" in "dev_web_start") + + echo "==> Generating OpenAPI schema..." + python manage.py spectacular --color --file schema.yml + echo "==> Creating migrations..." python manage.py makemigrations hhub diff --git a/hhub/settings.py b/hhub/settings.py index 9e3fd3f..9229abb 100644 --- a/hhub/settings.py +++ b/hhub/settings.py @@ -51,8 +51,22 @@ "corsheaders", # Used to run separate scripts that interact with the models (sync_db) "django_extensions", + "drf_spectacular", ] +# REST Framework +# https://www.django-rest-framework.org/api-guide/settings/ + +REST_FRAMEWORK = { + "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", +} + +SPECTACULAR_SETTINGS = { + "TITLE": "Homebrew Hub", + "DESCRIPTION": " A digital repository of of homebrew games, patches, hackroms for old consoles.", + "VERSION": "1.0.0", +} + MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", diff --git a/hhub/urls.py b/hhub/urls.py index 05fdb12..950e9bd 100644 --- a/hhub/urls.py +++ b/hhub/urls.py @@ -15,6 +15,10 @@ """ from django.urls import include, path +from drf_spectacular.views import ( + SpectacularAPIView, + SpectacularSwaggerView, +) from hhub import views @@ -24,6 +28,14 @@ r"api/", include( [ + # Serve the OpenAPI schema + path("schema/", SpectacularAPIView.as_view(), name="schema"), + # Serve the Swagger UI to browse the OpenAPI schema + path( + "schema/swagger-ui/", + SpectacularSwaggerView.as_view(url_name="schema"), + name="swagger-ui", + ), path("entry/.json", views.entry_manifest), path("all", views.entries_all), path("stats", views.stats), diff --git a/hhub/views.py b/hhub/views.py index 1d4ab27..ce84356 100644 --- a/hhub/views.py +++ b/hhub/views.py @@ -8,6 +8,11 @@ from hhub.models import Entry from hhub.serializers import EntrySerializer +from drf_spectacular.utils import extend_schema +from drf_spectacular.types import OpenApiTypes + +from rest_framework.decorators import api_view + def entry_manifest(request, pk): """ @@ -190,6 +195,12 @@ def search_entries(request): ) +@extend_schema( + summary="Get statistics about the entries in the database", + description="Retrieve aggregated counts of entries by type, tags, and platforms.", + responses={200: OpenApiTypes.OBJECT}, +) +@api_view(["GET"]) def stats(request): entries = Entry.objects data = { diff --git a/requirements.txt b/requirements.txt index 38018ce..ac9cd38 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,21 @@ asgiref==3.8.1 +attrs==24.2.0 black==24.10.0 cfgv==3.4.0 click==8.1.7 distlib==0.3.9 -dj_database_url==2.2.0 -Django==4.2.16 +dj-database-url==2.2.0 +django==4.2.16 django-cors-headers==4.5.0 django-extensions==3.2.3 djangorestframework==3.15.2 +drf-spectacular==0.28.0 filelock==3.16.1 identify==2.6.1 +inflection==0.5.1 isort==5.13.2 +jsonschema==4.23.0 +jsonschema-specifications==2024.10.1 mypy-extensions==1.0.0 nodeenv==1.9.1 pathspec==0.12.1 @@ -19,10 +24,13 @@ pre-commit==4.0.1 psycopg2==2.9.10 python-dateutil==2.9.0.post0 pytz==2024.2 -PyYAML==6.0.2 +pyyaml==6.0.2 +referencing==0.35.1 +rpds-py==0.22.3 +six==1.17.0 sqlparse==0.5.1 toml==0.10.2 tomli==2.0.2 -typing_extensions==4.12.2 +typing-extensions==4.12.2 +uritemplate==4.1.1 virtualenv==20.27.0 -six==1.17.0