From 1a2e50900d1d753a178994edec3bed680af6747d Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Wed, 29 Oct 2025 10:48:52 +0545 Subject: [PATCH] feat: add option to configure database connection via DATABASE_URL --- src/scripts/files.py | 8 +++++-- src/scripts/input_handler.py | 31 ++++++++++++++++++++++++++++ src/scripts/settings.py | 3 ++- src/templates/env_sample.j2 | 10 +++++---- src/templates/requirements.j2 | 2 +- src/templates/settings_production.j2 | 28 +++++++++++++------------ 6 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/scripts/files.py b/src/scripts/files.py index 995a834..3ed3627 100644 --- a/src/scripts/files.py +++ b/src/scripts/files.py @@ -30,7 +30,8 @@ class FileManager: def create_requirements(self) -> bool: with change_cwd(self.project_root): - requirements_content = template_engine.render_template("requirements.j2", {}) + context = {"use_database_url": self.metadata.get("use_database_url", True)} + requirements_content = template_engine.render_template("requirements.j2", context) return create_file_with_content( "requirements.txt", requirements_content, @@ -50,7 +51,10 @@ class FileManager: def create_env_file(self) -> bool: """Create .env.sample file with environment variables.""" with change_cwd(self.project_root): - context = {"project_name": self.project_name} + context = { + "project_name": self.project_name, + "use_database_url": self.metadata.get("use_database_url", True) + } env_content = template_engine.render_template("env_sample.j2", context) return create_file_with_content( ".env.sample", diff --git a/src/scripts/input_handler.py b/src/scripts/input_handler.py index e894997..b0b63c0 100644 --- a/src/scripts/input_handler.py +++ b/src/scripts/input_handler.py @@ -33,6 +33,7 @@ class ProjectMetadata: use_gitlab_ci: bool = False nested_apps: bool = False nested_dir: str | None = None + use_database_url: bool = False def to_dict(self) -> dict: """Convert to dictionary format.""" @@ -42,6 +43,7 @@ class ProjectMetadata: "use_gitlab_ci": self.use_gitlab_ci, "nested_apps": self.nested_apps, "nested_dir": self.nested_dir, + "use_database_url": self.use_database_url, } @@ -229,6 +231,27 @@ class InputCollector: ) return True, dir_name + def get_database_config_choice(self) -> bool: + """Ask user for database configuration preference.""" + UIFormatter.print_separator() + console.print(f"\n[{UIColors.INFO}]Database Configuration[/{UIColors.INFO}]\n") + console.print(f"[{UIColors.MUTED}]Choose how to configure your database in production:[/{UIColors.MUTED}]") + console.print() + console.print(f" [{UIColors.SUCCESS}]Y[/{UIColors.SUCCESS}] Use DATABASE_URL (recommended for production)") + console.print(f" [{UIColors.SUCCESS}]N[/{UIColors.SUCCESS}] Use individual database parameters") + console.print() + console.print(f"[{UIColors.MUTED}]DATABASE_URL is a single environment variable like:[/{UIColors.MUTED}]") + console.print(f"[{UIColors.MUTED}]postgres://user:password@host:port/database[/{UIColors.MUTED}]") + console.print() + + console.print(f"[{UIColors.HIGHLIGHT}]Use DATABASE_URL? (Y/n):[/{UIColors.HIGHLIGHT}] ", end="") + sys.stdout.flush() + choice = self.char_reader.get_char() + console.print(choice.upper()) + + # Default to True (use DATABASE_URL) if user presses Enter or Y + return choice.lower() != "n" + class CharReader: """Handles single character input across platforms.""" @@ -312,6 +335,9 @@ def get_user_input() -> Tuple[str, str, str, list, dict]: # Section 3: CI/CD Pipeline use_github, use_gitlab = collector.get_cicd_choice() + # Section 4: Database Configuration + use_database_url = collector.get_database_config_choice() + # Create metadata metadata = ProjectMetadata( package_name=project_dir, @@ -319,6 +345,7 @@ def get_user_input() -> Tuple[str, str, str, list, dict]: use_gitlab_ci=use_gitlab, nested_apps=nested, nested_dir=nested_dir, + use_database_url=use_database_url, ) console.print() @@ -344,6 +371,10 @@ def confirm_setup(project_dir: str, project_name: str, app_names: list, metadata cicd_choices = _get_cicd_display(metadata) console.print(f"[{UIColors.HIGHLIGHT}]CI/CD:[/{UIColors.HIGHLIGHT}] {cicd_choices}") + # Show database configuration + db_config = "DATABASE_URL" if metadata.get('use_database_url', True) else "Individual parameters" + console.print(f"[{UIColors.HIGHLIGHT}]Database Config:[/{UIColors.HIGHLIGHT}] {db_config}") + console.print() UIFormatter.print_separator() console.print() diff --git a/src/scripts/settings.py b/src/scripts/settings.py index 8ef45ea..048dd3b 100644 --- a/src/scripts/settings.py +++ b/src/scripts/settings.py @@ -73,7 +73,8 @@ class SettingsManager: def update_production_settings(self) -> bool: """Update production.py with production-specific settings.""" with change_cwd(self.settings_folder): - prod_content = template_engine.render_template("settings_production.j2", {}) + context = {"use_database_url": self.metadata.get("use_database_url", True)} + prod_content = template_engine.render_template("settings_production.j2", context) return create_file_with_content( "production.py", prod_content, diff --git a/src/templates/env_sample.j2 b/src/templates/env_sample.j2 index df900cc..7edee66 100644 --- a/src/templates/env_sample.j2 +++ b/src/templates/env_sample.j2 @@ -3,15 +3,17 @@ DJANGO_SETTINGS_MODULE={{ project_name }}.settings.development SECRET_KEY= your-secret-key ALLOWED_HOSTS=api.your-domain.com,www.your-domain.com -# Database URL (Option 1) -DATABASE_URL= - -# Database (Option 2) +{% if use_database_url %} +# Database URL (recommended for production) +DATABASE_URL=postgres://user:password@host:port/database_name +{% else %} +# Database (individual parameters) DB_NAME= DB_USER= DB_PASSWORD= DB_HOST= DB_PORT= +{% endif %} # Email settings EMAIL_HOST= diff --git a/src/templates/requirements.j2 b/src/templates/requirements.j2 index ff7d2bf..365c06d 100644 --- a/src/templates/requirements.j2 +++ b/src/templates/requirements.j2 @@ -8,4 +8,4 @@ django-cors-headers whitenoise psycopg2-binary gunicorn -dj-database-url +{% if use_database_url %}dj-database-url{% endif %} diff --git a/src/templates/settings_production.j2 b/src/templates/settings_production.j2 index b815894..6d45aa1 100644 --- a/src/templates/settings_production.j2 +++ b/src/templates/settings_production.j2 @@ -7,22 +7,24 @@ SECRET_KEY = os.getenv('SECRET_KEY') ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '').split(',') # Database -# Option 1: Using dj_database_url (recommended for production) +{% if use_database_url %} +# Using dj_database_url (recommended for production) DATABASES = { 'default': dj_database_url.parse(os.getenv('DATABASE_URL')) } - -# Option 2: Individual database parameters (uncomment to use) -# DATABASES = { -# 'default': { -# 'ENGINE': 'django.db.backends.postgresql', -# 'NAME': os.getenv('DB_NAME'), -# 'USER': os.getenv('DB_USER'), -# 'PASSWORD': os.getenv('DB_PASSWORD'), -# 'HOST': os.getenv('DB_HOST'), -# 'PORT': os.getenv('DB_PORT'), -# } -# } +{% else %} +# Using individual database parameters +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.getenv('DB_NAME'), + 'USER': os.getenv('DB_USER'), + 'PASSWORD': os.getenv('DB_PASSWORD'), + 'HOST': os.getenv('DB_HOST'), + 'PORT': os.getenv('DB_PORT'), + } +} +{% endif %}