Merge branch 'main' into dependabot/github_actions/actions/setup-python-6
This commit is contained in:
19 files changed
+80
-152
No files matched your search
@@ -4,6 +4,8 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
target-branch: "main"
|
||||
rebase-strategy: "auto"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "github-actions"
|
||||
@@ -12,8 +14,9 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
target-branch: "main"
|
||||
rebase-strategy: "auto"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "python"
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
@@ -44,4 +44,3 @@ jobs:
|
||||
- name: Test console script entry point
|
||||
run: |
|
||||
djinit --help
|
||||
|
||||
@@ -31,4 +31,3 @@ jobs:
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
@@ -23,6 +23,7 @@ jobs:
|
||||
steps.metadata.outputs.update-type == 'version-update:semver-patch'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.pulls.createReview({
|
||||
owner: context.repo.owner,
|
||||
@@ -37,6 +38,5 @@ jobs:
|
||||
steps.metadata.outputs.update-type == 'version-update:semver-patch'
|
||||
uses: peter-evans/enable-pull-request-automerge@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
merge-method: squash
|
||||
|
||||
@@ -27,4 +27,3 @@ jobs:
|
||||
- name: Run pre-commit
|
||||
run: |
|
||||
pre-commit run --all-files
|
||||
|
||||
@@ -18,4 +18,3 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
|
||||
@@ -22,8 +22,6 @@ ignore = [
|
||||
"__init__.py" = ["F401"] # imported but unused
|
||||
|
||||
[format]
|
||||
docstring-code-format = true
|
||||
indent-style = "space"
|
||||
skip-magic-trailing-comma = false
|
||||
line-ending = "auto"
|
||||
|
||||
@@ -17,7 +17,6 @@ setup(
|
||||
"rich>=14.2.0",
|
||||
"jinja2>=3.1.0",
|
||||
# "django<=5.2.7",
|
||||
|
||||
],
|
||||
entry_points={"console_scripts": ["djinit=src.generator:main"]},
|
||||
classifiers=[
|
||||
|
||||
@@ -5,7 +5,6 @@ Handles creation of Django apps and updating settings.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from src.scripts.console_ui import UIFormatter
|
||||
@@ -54,23 +53,18 @@ class AppManager:
|
||||
def _create_django_app(self) -> bool:
|
||||
# Detect project structure
|
||||
is_nested, nested_dir, apps_base_dir = self._detect_project_structure()
|
||||
|
||||
|
||||
# manage.py is always in the project root (current_dir), not in the project directory
|
||||
manage_py_path = os.path.join(self.current_dir, "manage.py")
|
||||
if not os.path.exists(manage_py_path):
|
||||
UIFormatter.print_error("Could not find manage.py file in project root")
|
||||
return False
|
||||
|
||||
|
||||
# Create app in the correct location
|
||||
with change_cwd(apps_base_dir):
|
||||
UIFormatter.print_info(f"Creating app '{self.app_name}' in directory: {os.getcwd()}")
|
||||
|
||||
result = subprocess.run(
|
||||
["django-admin", "startapp", self.app_name],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
|
||||
subprocess.run(["django-admin", "startapp", self.app_name], capture_output=True, text=True, check=True)
|
||||
|
||||
UIFormatter.print_success(f"Created Django app '{self.app_name}' in {apps_base_dir}")
|
||||
return True
|
||||
@@ -93,20 +87,20 @@ class AppManager:
|
||||
|
||||
# Detect project structure to determine the correct app module path
|
||||
is_nested, nested_dir, apps_base_dir = self._detect_project_structure()
|
||||
|
||||
|
||||
# Determine the correct module path for the app
|
||||
if is_nested and nested_dir:
|
||||
app_module_path = f"{nested_dir}.{self.app_name}"
|
||||
else:
|
||||
app_module_path = self.app_name
|
||||
|
||||
|
||||
UIFormatter.print_info(f"App module path: {app_module_path}")
|
||||
|
||||
# Check if app is already in USER_DEFINED_APPS section specifically
|
||||
lines = content.split("\n")
|
||||
in_user_apps = False
|
||||
app_already_exists = False
|
||||
|
||||
|
||||
for line in lines:
|
||||
if "USER_DEFINED_APPS" in line and "=" in line:
|
||||
in_user_apps = True
|
||||
@@ -197,7 +191,7 @@ class AppManager:
|
||||
# Step 2: try to infer nested_dir from USER_DEFINED_APPS in base.py
|
||||
try:
|
||||
if settings_base_path and os.path.exists(settings_base_path):
|
||||
with open(settings_base_path, "r") as f:
|
||||
with open(settings_base_path) as f:
|
||||
base_content = f.read()
|
||||
# Find lines inside USER_DEFINED_APPS and extract first dotted app
|
||||
in_user_apps = False
|
||||
@@ -209,7 +203,7 @@ class AppManager:
|
||||
break
|
||||
if in_user_apps:
|
||||
line_stripped = line.strip().strip(",")
|
||||
if line_stripped.startswith("\"") or line_stripped.startswith("'"):
|
||||
if line_stripped.startswith('"') or line_stripped.startswith("'"):
|
||||
app_label = line_stripped.strip("\"'")
|
||||
if "." in app_label:
|
||||
prefix = app_label.split(".", 1)[0]
|
||||
@@ -243,7 +237,7 @@ class AppManager:
|
||||
# Detect project structure to get correct app path
|
||||
is_nested, nested_dir, apps_base_dir = self._detect_project_structure()
|
||||
app_path = os.path.join(apps_base_dir, self.app_name)
|
||||
|
||||
|
||||
# Create serializers.py
|
||||
context = {"app_name": self.app_name}
|
||||
serializers_content = template_engine.render_template("serializers.j2", context)
|
||||
|
||||
@@ -25,7 +25,7 @@ class CICDConfigGenerator:
|
||||
create_file_with_content(
|
||||
workflow_file,
|
||||
workflow_content,
|
||||
f"Created Github Actions workflow ({workflow_file})",
|
||||
"Created Github Actions workflow (ci.yml)",
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -36,6 +36,6 @@ class CICDConfigGenerator:
|
||||
create_file_with_content(
|
||||
".gitlab-ci.yml",
|
||||
gitlab_ci_content,
|
||||
f"Created GitLab CI configuration (.gitlab-ci.yml)",
|
||||
"Created GitLab CI configuration (.gitlab-ci.yml)",
|
||||
)
|
||||
return True
|
||||
@@ -26,9 +26,7 @@ def parse_arguments() -> argparse.Namespace:
|
||||
secret_parser.add_argument("--length", type=int, default=50, help="Length of each secret key")
|
||||
|
||||
# App command
|
||||
app_parser = subparsers.add_parser(
|
||||
"app", help="Create one or more Django apps (comma or space separated)"
|
||||
)
|
||||
app_parser = subparsers.add_parser("app", help="Create one or more Django apps (comma or space separated)")
|
||||
app_parser.add_argument(
|
||||
"app_name",
|
||||
nargs="+",
|
||||
@@ -132,15 +130,11 @@ def handle_app_command(args: argparse.Namespace) -> None:
|
||||
|
||||
instructions = Text()
|
||||
instructions.append("🚀 Next Steps:\n", style=UIColors.ACCENT)
|
||||
instructions.append(
|
||||
"1. The app(s) have been added to INSTALLED_APPS in settings/base.py\n"
|
||||
)
|
||||
instructions.append("1. The app(s) have been added to INSTALLED_APPS in settings/base.py\n")
|
||||
instructions.append("2. Create your models in each app's models.py\n")
|
||||
instructions.append("3. Run migrations: python manage.py makemigrations\n")
|
||||
instructions.append("4. Apply migrations: python manage.py migrate\n")
|
||||
instructions.append(
|
||||
"5. Create views, serializers and routes(URLs) for your app(s)\n"
|
||||
)
|
||||
instructions.append("5. Create views, serializers and routes(URLs) for your app(s)\n")
|
||||
|
||||
console.print(Panel(instructions, title="💡 What's Next", border_style="green"))
|
||||
UIFormatter.print_info("")
|
||||
+41
-98
@@ -3,22 +3,23 @@ Console UI utilities for djinit.
|
||||
Provides enhanced styling, formatting, and user interface components.
|
||||
"""
|
||||
|
||||
from typing import List, Optional, Dict, Any
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from rich import box
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.progress import (
|
||||
BarColumn,
|
||||
Progress,
|
||||
SpinnerColumn,
|
||||
BarColumn,
|
||||
TaskProgressColumn,
|
||||
TextColumn,
|
||||
TimeRemainingColumn,
|
||||
)
|
||||
from rich.syntax import Syntax
|
||||
from rich.text import Text
|
||||
from rich.panel import Panel
|
||||
from rich.table import Table
|
||||
from rich import box
|
||||
from contextlib import contextmanager
|
||||
from rich.text import Text
|
||||
|
||||
console = Console()
|
||||
|
||||
@@ -65,37 +66,25 @@ class UIFormatter:
|
||||
|
||||
@staticmethod
|
||||
def print_success(message: str, icon: str = Icons.SUCCESS):
|
||||
console.print(
|
||||
f"[{UIColors.SUCCESS}]{icon}[/{UIColors.SUCCESS}] [bold]{message}[/bold]"
|
||||
)
|
||||
console.print(f"[{UIColors.SUCCESS}]{icon}[/{UIColors.SUCCESS}] [bold]{message}[/bold]")
|
||||
|
||||
@staticmethod
|
||||
def print_error(
|
||||
message: str, icon: str = Icons.ERROR, details: Optional[str] = None
|
||||
):
|
||||
def print_error(message: str, icon: str = Icons.ERROR, details: Optional[str] = None):
|
||||
"""Print error message with optional details"""
|
||||
console.print(
|
||||
f"[{UIColors.ERROR}]{icon}[/{UIColors.ERROR}] [bold]{message}[/bold]"
|
||||
)
|
||||
console.print(f"[{UIColors.ERROR}]{icon}[/{UIColors.ERROR}] [bold]{message}[/bold]")
|
||||
if details:
|
||||
console.print(f" [dim]{details}[/dim]")
|
||||
|
||||
@staticmethod
|
||||
def print_warning(message: str, icon: str = Icons.WARNING):
|
||||
console.print(
|
||||
f"[{UIColors.WARNING}]{icon}[/{UIColors.WARNING}] [bold]{message}[/bold]"
|
||||
)
|
||||
console.print(f"[{UIColors.WARNING}]{icon}[/{UIColors.WARNING}] [bold]{message}[/bold]")
|
||||
|
||||
@staticmethod
|
||||
def print_info(message: str, icon: str = Icons.INFO):
|
||||
console.print(
|
||||
f"[{UIColors.INFO}]{icon}[/{UIColors.INFO}] [bold]{message}[/bold]"
|
||||
)
|
||||
console.print(f"[{UIColors.INFO}]{icon}[/{UIColors.INFO}] [bold]{message}[/bold]")
|
||||
|
||||
@staticmethod
|
||||
def print_step(
|
||||
step_number: int, total_steps: int, description: str, icon: str = ""
|
||||
):
|
||||
def print_step(step_number: int, total_steps: int, description: str, icon: str = ""):
|
||||
"""Print step information with enhanced progress indicator"""
|
||||
icon_str = f"{icon} " if icon else ""
|
||||
percentage = int((step_number / total_steps) * 100)
|
||||
@@ -116,9 +105,7 @@ class UIFormatter:
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_live_progress(
|
||||
description: str = "Setup Progress", total_steps: int = 100
|
||||
):
|
||||
def create_live_progress(description: str = "Setup Progress", total_steps: int = 100):
|
||||
"""Create a live progress display that updates in place"""
|
||||
progress = Progress(
|
||||
SpinnerColumn(),
|
||||
@@ -152,10 +139,8 @@ class UIFormatter:
|
||||
@staticmethod
|
||||
def print_feature_list(features: List[str], icon: str = Icons.STAR):
|
||||
"""Print a styled feature list with custom icons"""
|
||||
for i, feature in enumerate(features, 1):
|
||||
console.print(
|
||||
f"[{UIColors.ACCENT}] {icon}[/{UIColors.ACCENT}] [bold]{feature}[/bold]"
|
||||
)
|
||||
for _i, feature in enumerate(features, 1):
|
||||
console.print(f"[{UIColors.ACCENT}] {icon}[/{UIColors.ACCENT}] [bold]{feature}[/bold]")
|
||||
|
||||
@staticmethod
|
||||
def print_numbered_list(items: List[str], start: int = 1):
|
||||
@@ -166,9 +151,7 @@ class UIFormatter:
|
||||
console.print(f" [dim]{prefix}[/dim] [dim]{i}.[/dim] {item}")
|
||||
|
||||
@staticmethod
|
||||
def print_tree_item(
|
||||
text: str, is_last: bool = False, indent: int = 0, icon: str = ""
|
||||
):
|
||||
def print_tree_item(text: str, is_last: bool = False, indent: int = 0, icon: str = ""):
|
||||
"""Print a tree-style item"""
|
||||
prefix = "└─" if is_last else "├─"
|
||||
icon_str = f"{icon} " if icon else ""
|
||||
@@ -183,15 +166,11 @@ class UIFormatter:
|
||||
line_numbers: bool = True,
|
||||
):
|
||||
"""Print code with syntax highlighting and customization"""
|
||||
syntax = Syntax(
|
||||
code, language, theme=theme, line_numbers=line_numbers, word_wrap=True
|
||||
)
|
||||
syntax = Syntax(code, language, theme=theme, line_numbers=line_numbers, word_wrap=True)
|
||||
console.print(syntax)
|
||||
|
||||
@staticmethod
|
||||
def print_panel(
|
||||
content: str, title: str = "", style: str = "cyan", border_style: str = "blue"
|
||||
):
|
||||
def print_panel(content: str, title: str = "", style: str = "cyan", border_style: str = "blue"):
|
||||
"""Print content in a styled panel"""
|
||||
panel = Panel(
|
||||
content,
|
||||
@@ -208,9 +187,7 @@ class UIFormatter:
|
||||
if not data:
|
||||
return
|
||||
|
||||
table = Table(
|
||||
title=title, box=box.ROUNDED, show_header=True, header_style="bold cyan"
|
||||
)
|
||||
table = Table(title=title, box=box.ROUNDED, show_header=True, header_style="bold cyan")
|
||||
|
||||
# Add columns from first row
|
||||
for key in data[0].keys():
|
||||
@@ -245,9 +222,7 @@ class UIFormatter:
|
||||
style=UIColors.MUTED,
|
||||
)
|
||||
welcome_text.append(" Repository: ", style=UIColors.MUTED)
|
||||
welcome_text.append(
|
||||
"https://github.com/S4NKALP/djinit\n", style="blue underline"
|
||||
)
|
||||
welcome_text.append("https://github.com/S4NKALP/djinit\n", style="blue underline")
|
||||
welcome_text.append(" License: MIT\n", style=UIColors.MUTED)
|
||||
|
||||
return welcome_text
|
||||
@@ -266,63 +241,39 @@ class UIFormatter:
|
||||
if success:
|
||||
# Success header
|
||||
console.print(f"[bold green]{'═' * 70}[/bold green]")
|
||||
console.print(
|
||||
f"[bold green]{f'{Icons.PARTY} SETUP COMPLETE! {Icons.PARTY}'.center(70)}[/bold green]"
|
||||
)
|
||||
console.print(f"[bold green]{f'{Icons.PARTY} SETUP COMPLETE! {Icons.PARTY}'.center(70)}[/bold green]")
|
||||
console.print(f"[bold green]{'═' * 70}[/bold green]\n")
|
||||
|
||||
# Duration if provided
|
||||
if duration:
|
||||
console.print(
|
||||
f"[dim]{Icons.CLOCK} Completed in {duration:.2f} seconds[/dim]\n"
|
||||
)
|
||||
console.print(f"[dim]{Icons.CLOCK} Completed in {duration:.2f} seconds[/dim]\n")
|
||||
|
||||
# Project details
|
||||
console.print(f"[bold cyan]{Icons.TARGET} Project Details:[/bold cyan]")
|
||||
console.print(" [dim]│[/dim]")
|
||||
console.print(
|
||||
f" [dim]├─[/dim] [bold]Directory:[/bold] [white]{project_dir}[/white]"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]├─[/dim] [bold]Project:[/bold] [white]{project_name}[/white]"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]└─[/dim] [bold]Apps:[/bold] [white]{', '.join(app_names)}[/white]"
|
||||
)
|
||||
console.print(f" [dim]├─[/dim] [bold]Directory:[/bold] [white]{project_dir}[/white]")
|
||||
console.print(f" [dim]├─[/dim] [bold]Project:[/bold] [white]{project_name}[/white]")
|
||||
console.print(f" [dim]└─[/dim] [bold]Apps:[/bold] [white]{', '.join(app_names)}[/white]")
|
||||
console.print()
|
||||
|
||||
# Next steps
|
||||
console.print(f"[bold cyan]{Icons.ROCKET} Next Steps:[/bold cyan]")
|
||||
console.print(" [dim]│[/dim]")
|
||||
console.print(" [dim]├─[/dim] [dim]1.[/dim] Navigate to your project directory")
|
||||
console.print(" [dim]├─[/dim] [dim]2.[/dim] Set environment variables in .env file")
|
||||
console.print(" [dim]├─[/dim] [dim]3.[/dim] Run migrations: [cyan]python manage.py migrate[/cyan]")
|
||||
console.print(
|
||||
f" [dim]├─[/dim] [dim]1.[/dim] Navigate to your project directory"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]├─[/dim] [dim]2.[/dim] Set environment variables in .env file"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]├─[/dim] [dim]3.[/dim] Run migrations: [cyan]python manage.py migrate[/cyan]"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]├─[/dim] [dim]4.[/dim] Create superuser: [cyan]python manage.py createsuperuser[/cyan]"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]└─[/dim] [dim]5.[/dim] Start server: [cyan]python manage.py runserver[/cyan]"
|
||||
" [dim]├─[/dim] [dim]4.[/dim] Create superuser: [cyan]python manage.py createsuperuser[/cyan]"
|
||||
)
|
||||
console.print(" [dim]└─[/dim] [dim]5.[/dim] Start server: [cyan]python manage.py runserver[/cyan]")
|
||||
console.print()
|
||||
|
||||
# Useful URLs
|
||||
console.print(f"[bold cyan]{Icons.LINK} Useful URLs:[/bold cyan]")
|
||||
console.print(" [dim]│[/dim]")
|
||||
console.print(
|
||||
f" [dim]├─[/dim] Admin: [blue]http://localhost:8000/admin/[/blue]"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]├─[/dim] API Docs: [blue]http://localhost:8000/docs/[/blue]"
|
||||
)
|
||||
console.print(
|
||||
f" [dim]└─[/dim] API Schema: [blue]http://localhost:8000/schema/[/blue]"
|
||||
)
|
||||
console.print(" [dim]├─[/dim] Admin: [blue]http://localhost:8000/admin/[/blue]")
|
||||
console.print(" [dim]├─[/dim] API Docs: [blue]http://localhost:8000/docs/[/blue]")
|
||||
console.print(" [dim]└─[/dim] API Schema: [blue]http://localhost:8000/schema/[/blue]")
|
||||
console.print()
|
||||
|
||||
console.print(f"[bold green]{'═' * 70}[/bold green]\n")
|
||||
@@ -336,22 +287,18 @@ class UIFormatter:
|
||||
console.print("[red]The setup process encountered an error.[/red]\n")
|
||||
|
||||
# Troubleshooting
|
||||
console.print(
|
||||
f"[bold yellow]{Icons.MAGNIFIER} Troubleshooting Tips:[/bold yellow]"
|
||||
)
|
||||
console.print(f"[bold yellow]{Icons.MAGNIFIER} Troubleshooting Tips:[/bold yellow]")
|
||||
console.print(" [dim]│[/dim]")
|
||||
console.print(f" [dim]├─[/dim] Check the error messages above")
|
||||
console.print(f" [dim]├─[/dim] Ensure you have write permissions")
|
||||
console.print(f" [dim]├─[/dim] Verify Django is installed correctly")
|
||||
console.print(f" [dim]└─[/dim] Try running with elevated permissions")
|
||||
console.print(" [dim]├─[/dim] Check the error messages above")
|
||||
console.print(" [dim]├─[/dim] Ensure you have write permissions")
|
||||
console.print(" [dim]├─[/dim] Verify Django is installed correctly")
|
||||
console.print(" [dim]└─[/dim] Try running with elevated permissions")
|
||||
console.print()
|
||||
|
||||
console.print(f"[bold red]{'═' * 70}[/bold red]\n")
|
||||
|
||||
@staticmethod
|
||||
def create_progress_display(
|
||||
description: str = "Processing", total_steps: int = 100
|
||||
):
|
||||
def create_progress_display(description: str = "Processing", total_steps: int = 100):
|
||||
"""Create a comprehensive live progress display"""
|
||||
progress = Progress(
|
||||
SpinnerColumn(),
|
||||
@@ -374,11 +321,7 @@ class UIFormatter:
|
||||
def confirm(prompt: str, default: bool = True) -> bool:
|
||||
"""Display a confirmation prompt"""
|
||||
default_str = "Y/n" if default else "y/N"
|
||||
response = (
|
||||
console.input(f"[bold cyan]?[/bold cyan] {prompt} [{default_str}]: ")
|
||||
.strip()
|
||||
.lower()
|
||||
)
|
||||
response = console.input(f"[bold cyan]?[/bold cyan] {prompt} [{default_str}]: ").strip().lower()
|
||||
|
||||
if not response:
|
||||
return default
|
||||
|
||||
@@ -77,7 +77,7 @@ tmp_upload_dir = None
|
||||
create_file_with_content(
|
||||
"gunicorn_config.py",
|
||||
gunicorn_config_content,
|
||||
f"Created gunicorn_config.py with Gunicorn configuration",
|
||||
"Created gunicorn_config.py with Gunicorn configuration",
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -88,7 +88,7 @@ tmp_upload_dir = None
|
||||
create_file_with_content(
|
||||
"runtime.txt",
|
||||
runtime_content,
|
||||
f"Created runtime.txt with Python version specification",
|
||||
"Created runtime.txt with Python version specification",
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -113,6 +113,6 @@ cmd = "gunicorn {self.project_name}.wsgi:application --bind 0.0.0.0:$PORT"
|
||||
create_file_with_content(
|
||||
"nixpacks.toml",
|
||||
nixpacks_content,
|
||||
f"Created nixpacks.toml for Nixpacks deployment",
|
||||
"Created nixpacks.toml for Nixpacks deployment",
|
||||
)
|
||||
return True
|
||||
@@ -53,7 +53,7 @@ class FileManager:
|
||||
with change_cwd(self.project_root):
|
||||
context = {
|
||||
"project_name": self.project_name,
|
||||
"use_database_url": self.metadata.get("use_database_url", True)
|
||||
"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(
|
||||
|
||||
@@ -203,8 +203,12 @@ class InputCollector:
|
||||
"""Ask whether to create nested Django apps and get directory name if yes."""
|
||||
UIFormatter.print_separator()
|
||||
console.print(f"\n[{UIColors.INFO}]Apps Layout[/{UIColors.INFO}]\n")
|
||||
console.print(f"[{UIColors.MUTED}]Do you want to place apps inside a package directory (e.g., 'apps/')?[/{UIColors.MUTED}]")
|
||||
console.print(f"[{UIColors.MUTED}]If yes, we'll create that directory as a Python package and generate apps inside it.[/{UIColors.MUTED}]")
|
||||
console.print(
|
||||
f"[{UIColors.MUTED}]Do you want to place apps inside a package directory (e.g., 'apps/')?[/{UIColors.MUTED}]"
|
||||
)
|
||||
console.print(
|
||||
f"[{UIColors.MUTED}]If yes, we'll create that directory as a Python package and generate apps inside it.[/{UIColors.MUTED}]"
|
||||
)
|
||||
console.print()
|
||||
|
||||
console.print(f"[{UIColors.HIGHLIGHT}]Nested Django apps? (y/N):[/{UIColors.HIGHLIGHT}] ", end="")
|
||||
@@ -270,7 +274,7 @@ class CharReader:
|
||||
# Fallback
|
||||
try:
|
||||
return msvcrt.getch().lower()
|
||||
except:
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
@staticmethod
|
||||
@@ -298,7 +302,7 @@ def get_user_input() -> Tuple[str, str, str, list, dict]:
|
||||
project_dir = collector.get_validated_input(
|
||||
"Enter project directory name", validate_project_name, "project directory name"
|
||||
)
|
||||
|
||||
|
||||
# Check if directory exists and ask for alternative
|
||||
while os.path.exists(project_dir):
|
||||
UIFormatter.print_error(f"Directory '{project_dir}' already exists.")
|
||||
@@ -364,7 +368,7 @@ def confirm_setup(project_dir: str, project_name: str, app_names: list, 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"
|
||||
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()
|
||||
|
||||
@@ -3,6 +3,7 @@ Project management for djinit.
|
||||
Handles creation of Django projects and apps.
|
||||
"""
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -65,9 +66,7 @@ class ProjectManager:
|
||||
return True
|
||||
|
||||
def _ensure_django_installed(self) -> None:
|
||||
try:
|
||||
import django
|
||||
except ImportError:
|
||||
if importlib.util.find_spec("django") is None:
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "pip", "install", "--upgrade", "django", "-q"],
|
||||
check=True,
|
||||
|
||||
@@ -27,9 +27,7 @@ def generate_multiple_keys(count: int = 3, length: int = 50) -> list[str]:
|
||||
|
||||
|
||||
def display_secret_keys(keys: list[str]) -> None:
|
||||
table = Table(
|
||||
title="🔐 Django Secret Keys", show_header=True, header_style="bold blue"
|
||||
)
|
||||
table = Table(title="🔐 Django Secret Keys", show_header=True, header_style="bold blue")
|
||||
table.add_column("Environment", style="cyan", no_wrap=True)
|
||||
table.add_column("Secret Key", style="dim")
|
||||
|
||||
|
||||
@@ -20,4 +20,4 @@ EMAIL_HOST=
|
||||
EMAIL_PORT=
|
||||
EMAIL_USE_TLS=
|
||||
EMAIL_HOST_USER=
|
||||
EMAIL_HOST_PASSWORD=
|
||||
EMAIL_HOST_PASSWORD=
|
||||
@@ -13,4 +13,4 @@ router = DefaultRouter()
|
||||
# router.register(r'{{ app_name }}', views.{{ app_name|title }}ViewSet)
|
||||
|
||||
# Get URL patterns
|
||||
urlpatterns = router.urls
|
||||
urlpatterns = router.urls
|
||||
Reference in new issue
Block a user