151 lines
5.4 KiB
Python
151 lines
5.4 KiB
Python
"""
|
|
App management for djinit.
|
|
Handles creation of Django apps and updating settings.
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
from typing import Optional
|
|
|
|
from src.scripts.console_ui import UIFormatter
|
|
from src.scripts.template_engine import template_engine
|
|
from src.utils import create_file_with_content
|
|
|
|
|
|
class AppManager:
|
|
def __init__(self, app_name: str):
|
|
self.app_name = app_name
|
|
self.current_dir = os.getcwd()
|
|
self.manage_py_path = os.path.join(self.current_dir, "manage.py")
|
|
|
|
def create_app(self) -> bool:
|
|
if not self._is_django_project():
|
|
UIFormatter.print_error(
|
|
"Not in a Django project directory. Please run this command from your Django project root."
|
|
)
|
|
return False
|
|
|
|
if self._app_exists():
|
|
UIFormatter.print_error(f"Django app '{self.app_name}' already exists.")
|
|
return False
|
|
|
|
if not self._create_django_app():
|
|
return False
|
|
|
|
if not self._add_to_installed_apps():
|
|
return False
|
|
|
|
if not self._create_additional_files():
|
|
return False
|
|
|
|
UIFormatter.print_success(f"Django app '{self.app_name}' created and configured successfully!")
|
|
return True
|
|
|
|
def _is_django_project(self) -> bool:
|
|
return os.path.exists(self.manage_py_path)
|
|
|
|
def _app_exists(self) -> bool:
|
|
app_path = os.path.join(self.current_dir, self.app_name)
|
|
return os.path.exists(app_path)
|
|
|
|
def _create_django_app(self) -> bool:
|
|
result = 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}'")
|
|
return True
|
|
|
|
def _add_to_installed_apps(self) -> bool:
|
|
settings_path = self._find_settings_path()
|
|
if not settings_path:
|
|
UIFormatter.print_error("Could not find Django settings directory")
|
|
return False
|
|
|
|
base_settings_path = os.path.join(settings_path, "base.py")
|
|
if not os.path.exists(base_settings_path):
|
|
UIFormatter.print_error("Could not find base.py settings file")
|
|
return False
|
|
|
|
with open(base_settings_path) as f:
|
|
content = f.read()
|
|
|
|
if f'"{self.app_name}"' in content or f"'{self.app_name}'" in content:
|
|
UIFormatter.print_info(f"App '{self.app_name}' is already in INSTALLED_APPS")
|
|
return True
|
|
|
|
if "USER_DEFINED_APPS" not in content:
|
|
UIFormatter.print_error("Could not find USER_DEFINED_APPS section in base.py")
|
|
return False
|
|
|
|
lines = content.split("\n")
|
|
new_lines = []
|
|
in_user_apps = False
|
|
apps_added = False
|
|
|
|
for line in lines:
|
|
if "USER_DEFINED_APPS" in line and "=" in line:
|
|
in_user_apps = True
|
|
new_lines.append(line)
|
|
elif in_user_apps and line.strip() == "]":
|
|
new_lines.append(f' "{self.app_name}",')
|
|
new_lines.append(line)
|
|
in_user_apps = False
|
|
apps_added = True
|
|
else:
|
|
new_lines.append(line)
|
|
|
|
if not apps_added:
|
|
UIFormatter.print_error("Could not find USER_DEFINED_APPS section in base.py")
|
|
return False
|
|
|
|
with open(base_settings_path, "w") as f:
|
|
f.write("\n".join(new_lines))
|
|
|
|
UIFormatter.print_success(f"Added '{self.app_name}' to USER_DEFINED_APPS in base.py")
|
|
return True
|
|
|
|
def _find_settings_path(self) -> Optional[str]:
|
|
# Look for project directories that contain settings
|
|
for item in os.listdir(self.current_dir):
|
|
if os.path.isdir(item) and not item.startswith(".") and item != "__pycache__":
|
|
# Check if this directory contains Django project files
|
|
project_path = os.path.join(self.current_dir, item)
|
|
settings_path = os.path.join(project_path, "settings")
|
|
|
|
# Check if settings directory exists with base.py
|
|
if os.path.exists(settings_path) and os.path.exists(os.path.join(settings_path, "base.py")):
|
|
return settings_path
|
|
|
|
# Fallback: look for settings in current directory
|
|
settings_path = os.path.join(self.current_dir, "settings")
|
|
if os.path.exists(settings_path) and os.path.exists(os.path.join(settings_path, "base.py")):
|
|
return settings_path
|
|
|
|
return None
|
|
|
|
def _create_additional_files(self) -> bool:
|
|
"""Create additional files for the app (serializers.py, routes.py)."""
|
|
app_path = os.path.join(self.current_dir, self.app_name)
|
|
|
|
# Create serializers.py
|
|
context = {"app_name": self.app_name}
|
|
serializers_content = template_engine.render_template("serializers.j2", context)
|
|
if not create_file_with_content(
|
|
os.path.join(app_path, "serializers.py"),
|
|
serializers_content,
|
|
f"Created {self.app_name}/serializers.py",
|
|
should_format=True,
|
|
):
|
|
return False
|
|
|
|
# Create routes.py
|
|
routes_content = template_engine.render_template("routes.j2", context)
|
|
if not create_file_with_content(
|
|
os.path.join(app_path, "routes.py"),
|
|
routes_content,
|
|
f"Created {self.app_name}/routes.py",
|
|
should_format=True,
|
|
):
|
|
return False
|
|
|
|
return True
|