From f3c11cbe2883a0b71fa3687304d5a7319a62a0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Gremaud?= Date: Fri, 12 Jun 2026 00:55:14 +0200 Subject: [PATCH] feat: add settings management --- .gitignore | 2 ++ highscore/.env.example | 11 +++++++++++ highscore/app/config.py | 24 ++++++++++++++++++++++++ highscore/app/settings.py | 27 ++++++++++++--------------- pyproject.toml | 3 +++ uv.lock | 39 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 highscore/.env.example create mode 100644 highscore/app/config.py diff --git a/.gitignore b/.gitignore index 505a3b1..1e73087 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ wheels/ # Virtual environments .venv + +.env diff --git a/highscore/.env.example b/highscore/.env.example new file mode 100644 index 0000000..56952b9 --- /dev/null +++ b/highscore/.env.example @@ -0,0 +1,11 @@ +DJANGO_SECRET_KEY=change-me +DEBUG=true +ALLOWED_HOSTS=[] +API_SECRET=selecta-secret + +DB_ENGINE=django.db.backends.postgresql +DB_NAME=selecta +DB_USER=postgres +DB_PASSWORD= +DB_HOST=localhost +DB_PORT=5432 diff --git a/highscore/app/config.py b/highscore/app/config.py new file mode 100644 index 0000000..600940f --- /dev/null +++ b/highscore/app/config.py @@ -0,0 +1,24 @@ +from pathlib import Path + +from pydantic_settings import BaseSettings, SettingsConfigDict + +BASE_DIR = Path(__file__).resolve().parent.parent + + +class Settings(BaseSettings): + model_config = SettingsConfigDict(env_file=BASE_DIR / ".env", env_file_encoding="utf-8") + + django_secret_key: str = "" + debug: bool = True + allowed_hosts: list[str] = [] + api_secret: str = "selecta-secret" + + db_engine: str = "django.db.backends.postgresql" + db_name: str = "selecta-highscore" + db_user: str = "postgres" + db_password: str = "" + db_host: str = "localhost" + db_port: int = 5432 + + +settings = Settings() diff --git a/highscore/app/settings.py b/highscore/app/settings.py index 1bd3b2f..8813258 100644 --- a/highscore/app/settings.py +++ b/highscore/app/settings.py @@ -12,20 +12,13 @@ https://docs.djangoproject.com/en/6.0/ref/settings/ from pathlib import Path -# Build paths inside the project like this: BASE_DIR / 'subdir'. +from app.config import settings as env + 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-i_1=_f%do@*t&q)!n^jh3cotravax72+65ctwm6u@slbdu+nr_" - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = [] +SECRET_KEY = env.django_secret_key +DEBUG = env.debug +ALLOWED_HOSTS = env.allowed_hosts # Application definition @@ -40,7 +33,7 @@ INSTALLED_APPS = [ "scores", ] -API_SECRET = "selecta-secret" +API_SECRET = env.api_secret MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", @@ -77,8 +70,12 @@ WSGI_APPLICATION = "app.wsgi.application" DATABASES = { "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", + "ENGINE": env.db_engine, + "NAME": env.db_name, + "USER": env.db_user, + "PASSWORD": env.db_password, + "HOST": env.db_host, + "PORT": env.db_port, } } diff --git a/pyproject.toml b/pyproject.toml index 4ded820..91944eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,8 @@ requires-python = ">=3.13" dependencies = [ "django>=6.0.6", "django-ninja>=1.6.2", + "psycopg>=3.3.4", + "pydantic-settings>=2.14.1", ] [dependency-groups] @@ -40,6 +42,7 @@ ignore = [ [tool.ruff.lint.per-file-ignores] "*/migrations/*.py" = ["E501"] "*/settings.py" = ["S105"] +"*/config.py" = ["S105"] [tool.ruff.lint.isort] known-first-party = ["app", "scores"] diff --git a/uv.lock b/uv.lock index 6c74163..fae618e 100644 --- a/uv.lock +++ b/uv.lock @@ -47,6 +47,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/21/0c/25f72060a39632fbd2d90e9c8b6052a09cd45b0598fc06c0758d313f0052/django_ninja-1.6.2-py3-none-any.whl", hash = "sha256:20095f5900bada22ea00cf1a58af50bdb285b2354c61a9d9b47d0dc89ac462d6", size = 2374994, upload-time = "2026-03-18T20:06:45.676Z" }, ] +[[package]] +name = "psycopg" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" }, +] + [[package]] name = "pydantic" version = "2.13.4" @@ -118,6 +130,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, ] +[[package]] +name = "pydantic-settings" +version = "2.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + [[package]] name = "ruff" version = "0.15.17" @@ -150,6 +185,8 @@ source = { virtual = "." } dependencies = [ { name = "django" }, { name = "django-ninja" }, + { name = "psycopg" }, + { name = "pydantic-settings" }, ] [package.dev-dependencies] @@ -161,6 +198,8 @@ dev = [ requires-dist = [ { name = "django", specifier = ">=6.0.6" }, { name = "django-ninja", specifier = ">=1.6.2" }, + { name = "psycopg", specifier = ">=3.3.4" }, + { name = "pydantic-settings", specifier = ">=2.14.1" }, ] [package.metadata.requires-dev]