From 94e03963803bba294190ce461417bbd211da022e Mon Sep 17 00:00:00 2001 From: Simonas Kareiva Date: Tue, 12 May 2026 17:05:08 +0300 Subject: [PATCH] Scaffold project structure --- apps/accounts/__init__.py | 0 apps/accounts/admin.py | 3 + apps/accounts/apps.py | 5 + apps/accounts/migrations/__init__.py | 0 apps/accounts/models.py | 3 + apps/accounts/tests.py | 3 + apps/accounts/views.py | 3 + apps/dashboard/__init__.py | 0 apps/dashboard/admin.py | 3 + apps/dashboard/apps.py | 5 + apps/dashboard/migrations/__init__.py | 0 apps/dashboard/models.py | 3 + apps/dashboard/tests.py | 3 + apps/dashboard/views.py | 3 + apps/submissions/__init__.py | 0 apps/submissions/admin.py | 3 + apps/submissions/apps.py | 5 + apps/submissions/migrations/__init__.py | 0 apps/submissions/models.py | 3 + apps/submissions/tests.py | 3 + apps/submissions/views.py | 3 + demo/confirmed.html | 74 ++++++++++ demo/detail-completed.html | 134 ++++++++++++++++++ demo/detail-pending.html | 153 +++++++++++++++++++++ demo/detail-printing.html | 134 ++++++++++++++++++ demo/detail-queued.html | 150 +++++++++++++++++++++ demo/detail-rejected.html | 128 ++++++++++++++++++ demo/index.html | 151 +++++++++++++++++++++ demo/login.html | 83 ++++++++++++ demo/my-prints.html | 129 ++++++++++++++++++ demo/submit-signed-in.html | 151 +++++++++++++++++++++ demo/submit.html | 172 ++++++++++++++++++++++++ hamprint/__init__.py | 0 hamprint/asgi.py | 16 +++ hamprint/settings.py | 117 ++++++++++++++++ hamprint/urls.py | 23 ++++ hamprint/wsgi.py | 16 +++ manage.py | 23 ++++ requirements.txt | 18 +++ 39 files changed, 1723 insertions(+) create mode 100644 apps/accounts/__init__.py create mode 100644 apps/accounts/admin.py create mode 100644 apps/accounts/apps.py create mode 100644 apps/accounts/migrations/__init__.py create mode 100644 apps/accounts/models.py create mode 100644 apps/accounts/tests.py create mode 100644 apps/accounts/views.py create mode 100644 apps/dashboard/__init__.py create mode 100644 apps/dashboard/admin.py create mode 100644 apps/dashboard/apps.py create mode 100644 apps/dashboard/migrations/__init__.py create mode 100644 apps/dashboard/models.py create mode 100644 apps/dashboard/tests.py create mode 100644 apps/dashboard/views.py create mode 100644 apps/submissions/__init__.py create mode 100644 apps/submissions/admin.py create mode 100644 apps/submissions/apps.py create mode 100644 apps/submissions/migrations/__init__.py create mode 100644 apps/submissions/models.py create mode 100644 apps/submissions/tests.py create mode 100644 apps/submissions/views.py create mode 100644 demo/confirmed.html create mode 100644 demo/detail-completed.html create mode 100644 demo/detail-pending.html create mode 100644 demo/detail-printing.html create mode 100644 demo/detail-queued.html create mode 100644 demo/detail-rejected.html create mode 100644 demo/index.html create mode 100644 demo/login.html create mode 100644 demo/my-prints.html create mode 100644 demo/submit-signed-in.html create mode 100644 demo/submit.html create mode 100644 hamprint/__init__.py create mode 100644 hamprint/asgi.py create mode 100644 hamprint/settings.py create mode 100644 hamprint/urls.py create mode 100644 hamprint/wsgi.py create mode 100755 manage.py create mode 100644 requirements.txt diff --git a/apps/accounts/__init__.py b/apps/accounts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/accounts/admin.py b/apps/accounts/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/accounts/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/accounts/apps.py b/apps/accounts/apps.py new file mode 100644 index 0000000..fb0257e --- /dev/null +++ b/apps/accounts/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AccountsConfig(AppConfig): + name = "accounts" diff --git a/apps/accounts/migrations/__init__.py b/apps/accounts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/accounts/models.py b/apps/accounts/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/apps/accounts/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/apps/accounts/tests.py b/apps/accounts/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/apps/accounts/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/accounts/views.py b/apps/accounts/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/apps/accounts/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/apps/dashboard/__init__.py b/apps/dashboard/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/dashboard/admin.py b/apps/dashboard/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/dashboard/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/dashboard/apps.py b/apps/dashboard/apps.py new file mode 100644 index 0000000..45b7fa2 --- /dev/null +++ b/apps/dashboard/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class DashboardConfig(AppConfig): + name = "dashboard" diff --git a/apps/dashboard/migrations/__init__.py b/apps/dashboard/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/dashboard/models.py b/apps/dashboard/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/apps/dashboard/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/apps/dashboard/tests.py b/apps/dashboard/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/apps/dashboard/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/dashboard/views.py b/apps/dashboard/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/apps/dashboard/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/apps/submissions/__init__.py b/apps/submissions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/submissions/admin.py b/apps/submissions/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/submissions/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/submissions/apps.py b/apps/submissions/apps.py new file mode 100644 index 0000000..f5e7f04 --- /dev/null +++ b/apps/submissions/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class SubmissionsConfig(AppConfig): + name = "submissions" diff --git a/apps/submissions/migrations/__init__.py b/apps/submissions/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/submissions/models.py b/apps/submissions/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/apps/submissions/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/apps/submissions/tests.py b/apps/submissions/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/apps/submissions/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/submissions/views.py b/apps/submissions/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/apps/submissions/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/demo/confirmed.html b/demo/confirmed.html new file mode 100644 index 0000000..e6ee577 --- /dev/null +++ b/demo/confirmed.html @@ -0,0 +1,74 @@ + + + + + +Email confirmed — hamprint + + + + + +
+ +
+ + + +
+
+
+ +
+

Email confirmed

+

Your submission cheerful_curie is now in the print queue.

+ + View your submission → + +

Redirecting in a few seconds…

+
+ +
+

Tip

+

Bookmark the submission page — it's the only way to find this print without an account. Or sign in with Google to see all your prints in one place.

+
+
+ + + + + diff --git a/demo/detail-completed.html b/demo/detail-completed.html new file mode 100644 index 0000000..faadf9f --- /dev/null +++ b/demo/detail-completed.html @@ -0,0 +1,134 @@ + + + + + +jolly_bardeen · completed — hamprint + + + + + +
+ +
+ + + +
+ +
+ +
+

Ready for pickup!

+

Your print is finished and waiting at the hamlab.lt space. See pickup instructions below.

+
+
+ +
+
+ Completed + Finished 3 hours ago +
+

jolly_bardeen

+
+ +
+
+
+

Pickup instructions

+

Shelf above the workbench in the main room, labelled with your codename on masking tape. Door code is in the Matrix channel pinned message. Please take the whole bag — brim is loose in there.

+
+ + + +
+ + +
+
+ + + + + diff --git a/demo/detail-pending.html b/demo/detail-pending.html new file mode 100644 index 0000000..d64d74d --- /dev/null +++ b/demo/detail-pending.html @@ -0,0 +1,153 @@ + + + + + +cheerful_curie · pending confirmation — hamprint + + + + + +
+ +
+ + + +
+ +
+ +
+

Check your inbox to confirm this submission

+

We sent a confirmation link to y••••@example.com. Click it within 1 hour or this submission will be permanently deleted (along with the uploaded STL).

+
+ + Expires in 52 min · 0 / 3 resends used +
+
+
+ + +
+
+ Pending confirmation + Not yet visible on the dashboard +
+

cheerful_curie

+
+ +
+ +
+
+

Source

+
+ +
+

spool_holder_v3.stl

+

2.1 MB · uploaded just now

+
+ Hidden until confirmed +
+
+ +
+ + + +
+
+ + + + + diff --git a/demo/detail-printing.html b/demo/detail-printing.html new file mode 100644 index 0000000..0ef5d68 --- /dev/null +++ b/demo/detail-printing.html @@ -0,0 +1,134 @@ + + + + + +cheerful_curie · printing — hamprint + + + + + +
+ +
+ + + +
+ +
+
+ +
+
+

Printing now

+

An operator is running this print at the hamlab.lt printer. Page refreshes every 30 s.

+
+
+ +
+
+ Printing + Started 12 minutes ago +
+

cheerful_curie

+
+ +
+
+
+

Source

+
+ +
+

spool_holder_v3.stl

+

2.1 MB

+
+ Download +
+
+ +
+

Notes from the operator

+

Slicing took 38 min in PrusaSlicer, 0.2 mm layers, 15% infill, red PLA from the shared spool. ETA ~2 h.

+
+
+ + +
+
+ + + + + diff --git a/demo/detail-queued.html b/demo/detail-queued.html new file mode 100644 index 0000000..3b40bfe --- /dev/null +++ b/demo/detail-queued.html @@ -0,0 +1,150 @@ + + + + + +sleepy_volta · queued — hamprint + + + + + +
+ +
+ + + +
+ +
+ +
+

In the queue · position #1

+

An operator will pick this up soon. This page refreshes automatically every 30 s.

+
+ +
+ + +
+
+
+ Queued + Submitted 42 minutes ago +
+

sleepy_volta

+
+ +
+ +
+ +
+ + +
+ + + +
+
+ + + + + diff --git a/demo/detail-rejected.html b/demo/detail-rejected.html new file mode 100644 index 0000000..c11486b --- /dev/null +++ b/demo/detail-rejected.html @@ -0,0 +1,128 @@ + + + + + +stoic_turing · rejected — hamprint + + + + + +
+ +
+ + + +
+ +
+ +
+

Submission rejected

+

An operator declined to print this. See the reason below.

+
+
+ +
+
+ Rejected + 3 days ago +
+

stoic_turing

+
+ +
+
+
+

Reason from the operator

+

Model is 340 × 280 mm — doesn't fit on our build plate (235 × 235 mm max). Also the part requires PETG/ABS for structural use, which we don't stock right now. Feel free to resubmit a scaled or split version.

+
+ +
+

Source

+
+ +
+

drone_frame_v2.stl

+

3.4 MB · raw .stl upload

+
+
+
+ +
+

Want to try again?

+

Adjust the model based on the operator's feedback and submit a new print.

+
+
+ + +
+
+ + + + + diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..33a3ce1 --- /dev/null +++ b/demo/index.html @@ -0,0 +1,151 @@ + + + + + +hamprint — public 3D print dashboard + + + + + + +
+ +
+ + + + +
+ +
+

Print dashboard

+

Every public print job submitted to the hamlab.lt printer. Look up your submission by its codename.

+
+ + +
+ + + + + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodenameStatus
cheerful_curiePrinting
sleepy_voltaQueued · #1
grumpy_hopperQueued · #2
jolly_bardeenCompleted
vibrant_lovelaceCompleted
stoic_turingRejected
brave_hamiltonCompleted
cool_einsteinCompleted
+
+ + +
+

Showing 1–8 of 42

+
+ + +
+
+ + +
+
?
+
+

Don't have an account?

+

You don't need one. Just hit Submit a print, give us an email, and we'll send you a codename to track your job.

+
+
+
+ + + + + diff --git a/demo/login.html b/demo/login.html new file mode 100644 index 0000000..4b144b5 --- /dev/null +++ b/demo/login.html @@ -0,0 +1,83 @@ + + + + + +Sign in — hamprint + + + + + +
+ +
+ + + +
+
+
+
h
+

Sign in to hamprint

+

Optional — you can also submit as a guest.

+
+ + + + Continue with Google + + + + +
+

Signed-in prints skip email confirmation.

+

See all your past prints in one place.

+

We don't share your email, ever.

+
+
+
+ + + + + diff --git a/demo/my-prints.html b/demo/my-prints.html new file mode 100644 index 0000000..3b22973 --- /dev/null +++ b/demo/my-prints.html @@ -0,0 +1,129 @@ + + + + + +My prints — hamprint + + + + + +
+ +
+ + + +
+
+
+

My prints

+

All prints submitted with linutas@gmail.com.

+
+
+ 14 total · 2 queued · 12 completed +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodenameSourceStatus
sleepy_voltaprintables.comQueued · #1
grumpy_hopper.stl uploadQueued · #2
vibrant_lovelacethingiverse.comCompleted
stoic_turing.stl uploadRejected
brave_hamilton.stl uploadCompleted
cool_einsteinprintables.comCompleted
+
+ + +
+ + + + + diff --git a/demo/submit-signed-in.html b/demo/submit-signed-in.html new file mode 100644 index 0000000..bf874fa --- /dev/null +++ b/demo/submit-signed-in.html @@ -0,0 +1,151 @@ + + + + + +Submit a print — hamprint + + + + + +
+ +
+ + + +
+
+

Submit a print

+

Your email is already verified through Google — this print goes straight to the queue.

+
+ + +
+ +

Signed in as linutas@gmail.com. No email confirmation needed.

+
+ +
+
+ Where is the model coming from? * +
+ + + + + + + + +
+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+ +

Got something from elsewhere? Download the .stl and upload it as a file.

+
+ +
+ + +

Only filaments currently loaded at hamlab.lt are listed.

+
+ +
+ + +

Only the operator sees these — they're not shown on your public submission page.

+
+ + +
+
+ + + + + diff --git a/demo/submit.html b/demo/submit.html new file mode 100644 index 0000000..419a74e --- /dev/null +++ b/demo/submit.html @@ -0,0 +1,172 @@ + + + + + +Submit a print — hamprint + + + + + +
+ +
+ + + +
+
+

Submit a print

+

Anyone can submit a job. We'll send you a codename to follow it on the dashboard.

+
+ + +
+ Guest +

You're submitting anonymously. We'll email you a confirmation link — click it within 1 hour to put your print in the queue. Sign in with Google to skip this step.

+
+ +
+ +
+ Where is the model coming from? * +
+ + + + + + + + + + + +
+ + +
+ +
+ + +
+ + +

Must be a printables.com link.

+
+ + +
+ + +

Must be a makerworld.com link.

+
+ + +
+ + +

Must be a thingiverse.com link.

+
+ +

Got something from elsewhere? Download the .stl and upload it as a file.

+
+ + +
+ + +

Only filaments currently loaded at hamlab.lt are listed. The list is curated by operators — out-of-stock options are hidden.

+
+ + +
+ + +

Only the operator sees these — they're not shown on your public submission page. Layer height, infill, pickup arrangement, anything useful.

+
+ + +
+ + +

We'll send a confirmation link. The submission disappears in 1 hour if not confirmed. Never shown publicly.

+
+ + + +
+
+ + + + + diff --git a/hamprint/__init__.py b/hamprint/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hamprint/asgi.py b/hamprint/asgi.py new file mode 100644 index 0000000..7cce10e --- /dev/null +++ b/hamprint/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for hamprint project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hamprint.settings") + +application = get_asgi_application() diff --git a/hamprint/settings.py b/hamprint/settings.py new file mode 100644 index 0000000..58cc046 --- /dev/null +++ b/hamprint/settings.py @@ -0,0 +1,117 @@ +""" +Django settings for hamprint project. + +Generated by 'django-admin startproject' using Django 6.0.5. + +For more information on this file, see +https://docs.djangoproject.com/en/6.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/6.0/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = "django-insecure-u0^726zo0+d#dbuhxc+^3^miv8#o^mlydn6j97%^%=2u!%nayn" + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +ROOT_URLCONF = "hamprint.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "hamprint.wsgi.application" + + +# Database +# https://docs.djangoproject.com/en/6.0/ref/settings/#databases + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + } +} + + +# Password validation +# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/6.0/topics/i18n/ + +LANGUAGE_CODE = "en-us" + +TIME_ZONE = "UTC" + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/6.0/howto/static-files/ + +STATIC_URL = "static/" diff --git a/hamprint/urls.py b/hamprint/urls.py new file mode 100644 index 0000000..63bbd03 --- /dev/null +++ b/hamprint/urls.py @@ -0,0 +1,23 @@ +""" +URL configuration for hamprint project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/6.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" + +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path("admin/", admin.site.urls), +] diff --git a/hamprint/wsgi.py b/hamprint/wsgi.py new file mode 100644 index 0000000..45a8003 --- /dev/null +++ b/hamprint/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for hamprint project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hamprint.settings") + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..4231c7d --- /dev/null +++ b/manage.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" + +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hamprint.settings") + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..afc9dcd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,18 @@ +asgiref==3.11.1 +certifi==2026.4.22 +charset-normalizer==3.4.7 +crispy-tailwind==1.0.3 +dj-database-url==3.1.2 +Django==6.0.5 +django-allauth==65.16.1 +django-anymail==15.0 +django-crispy-forms==2.6 +django-environ==0.13.0 +gunicorn==26.0.0 +idna==3.14 +namesgenerator==0.3 +packaging==26.2 +requests==2.34.0 +sqlparse==0.5.5 +urllib3==2.7.0 +whitenoise==6.12.0