From 0fde5c7aa803c8b6d27762c905d1901086001a71 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Sat, 31 Jan 2026 01:39:11 +0545 Subject: [PATCH] feat(djinit/templates): migrate templates to double-bracket placeholder syntax New Features - Adopt double-bracket placeholders (`[[ var ]]`) and rename templates to `.py-tpl`/.`md-tpl` extensions. - Introduce new `runtime_txt-tpl` template. Enhancements - Update `api_readme`, `models`, `apps`, `routes`, `pyproject`, `readme`, and `requirements` templates with new syntax and naming. - Align placeholder naming with a unified convention. Bug Fixes - None. --- .../components/{admin.j2 => admin.py-tpl} | 0 .../{api_readme.j2 => api_readme.md-tpl} | 6 +- djinit/templates/components/apps.j2 | 8 -- djinit/templates/components/apps.py-tpl | 6 + .../components/{models.j2 => models.py-tpl} | 2 - ...{models_readme.j2 => models_readme.md-tpl} | 2 +- djinit/templates/components/routes.j2 | 18 --- djinit/templates/components/routes.py-tpl | 8 ++ djinit/templates/components/serializers.j2 | 14 --- .../templates/components/serializers.py-tpl | 3 + .../components/{tests.j2 => tests.py-tpl} | 2 - djinit/templates/components/urls.j2 | 11 -- .../components/{views.j2 => views.py-tpl} | 2 - .../templates/config/{asgi.j2 => asgi.py-tpl} | 2 +- .../config/settings/{base.j2 => base.py-tpl} | 13 ++- .../{development.j2 => development.py-tpl} | 2 +- .../{production.j2 => production.py-tpl} | 12 +- djinit/templates/config/urls.py-tpl | 103 ++++++++++++++++++ djinit/templates/config/urls/base.j2 | 8 -- djinit/templates/config/urls/with_api.j2 | 30 ----- djinit/templates/config/urls/with_apps.j2 | 31 ------ .../templates/config/{wsgi.j2 => wsgi.py-tpl} | 2 +- .../templates/presets/predefined/api/urls.j2 | 7 -- .../presets/predefined/api/v1/urls.j2 | 7 -- .../presets/predefined/apps/generic/models.j2 | 8 -- .../predefined/apps/generic/models.py-tpl | 18 +++ .../predefined/apps/generic/serializers.j2 | 9 -- .../apps/generic/serializers.py-tpl | 11 ++ .../predefined/apps/generic/services.j2 | 10 -- .../predefined/apps/generic/services.py-tpl | 36 ++++++ .../presets/predefined/apps/generic/tests.j2 | 12 -- .../predefined/apps/generic/tests.py-tpl | 55 ++++++++++ .../presets/predefined/apps/generic/urls.j2 | 14 --- .../presets/predefined/apps/generic/views.j2 | 9 -- .../predefined/apps/generic/views.py-tpl | 62 +++++++++++ .../apps/users/{models.j2 => models.py-tpl} | 0 .../{serializers.j2 => serializers.py-tpl} | 0 .../users/{services.j2 => services.py-tpl} | 0 .../apps/users/{tests.j2 => tests.py-tpl} | 0 .../presets/predefined/apps/users/urls.j2 | 14 --- .../apps/users/{views.j2 => views.py-tpl} | 0 .../core/{exceptions.j2 => exceptions.py-tpl} | 0 ...equest_logger.j2 => request_logger.py-tpl} | 0 ...mped_model.j2 => timestamped_model.py-tpl} | 0 .../predefined/core/utils/responses.j2 | 9 -- .../core/utils/responses.py-tpl} | 8 +- .../apps/core/{apps.j2 => apps.py-tpl} | 0 .../{__init__.py.j2 => __init__.py-tpl} | 0 .../core/models/{base.py.j2 => base.py-tpl} | 0 .../models/{mixins.py.j2 => mixins.py-tpl} | 0 .../utils/{__init__.py.j2 => __init__.py-tpl} | 0 .../{github_actions.j2 => github_actions-tpl} | 4 +- .../ci/{gitlab_ci.j2 => gitlab_ci-tpl} | 14 +-- .../project/{env_sample.j2 => env_sample-tpl} | 18 +-- .../project/{gitignore.j2 => gitignore-tpl} | 0 djinit/templates/project/init.j2 | 0 .../init.py-tpl} | 0 .../project/{justfile.j2 => justfile-tpl} | 8 +- .../project/{manage_py.j2 => manage.py-tpl} | 2 +- .../project/{procfile.j2 => procfile-tpl} | 12 +- .../{pyproject_toml.j2 => pyproject.toml-tpl} | 8 +- .../project/{readme.j2 => readme.md-tpl} | 20 ++-- .../{requirements.j2 => requirements-tpl} | 8 +- djinit/templates/project/runtime_txt-tpl | 1 + djinit/templates/project/runtime_txt.j2 | 1 - 65 files changed, 378 insertions(+), 292 deletions(-) rename djinit/templates/components/{admin.j2 => admin.py-tpl} (100%) rename djinit/templates/components/{api_readme.j2 => api_readme.md-tpl} (92%) delete mode 100644 djinit/templates/components/apps.j2 create mode 100644 djinit/templates/components/apps.py-tpl rename djinit/templates/components/{models.j2 => models.py-tpl} (66%) rename djinit/templates/components/{models_readme.j2 => models_readme.md-tpl} (98%) delete mode 100644 djinit/templates/components/routes.j2 create mode 100644 djinit/templates/components/routes.py-tpl delete mode 100644 djinit/templates/components/serializers.j2 create mode 100644 djinit/templates/components/serializers.py-tpl rename djinit/templates/components/{tests.j2 => tests.py-tpl} (67%) delete mode 100644 djinit/templates/components/urls.j2 rename djinit/templates/components/{views.j2 => views.py-tpl} (68%) rename djinit/templates/config/{asgi.j2 => asgi.py-tpl} (79%) rename djinit/templates/config/settings/{base.j2 => base.py-tpl} (94%) rename djinit/templates/config/settings/{development.j2 => development.py-tpl} (97%) rename djinit/templates/config/settings/{production.j2 => production.py-tpl} (92%) create mode 100644 djinit/templates/config/urls.py-tpl delete mode 100644 djinit/templates/config/urls/base.j2 delete mode 100644 djinit/templates/config/urls/with_api.j2 delete mode 100644 djinit/templates/config/urls/with_apps.j2 rename djinit/templates/config/{wsgi.j2 => wsgi.py-tpl} (79%) delete mode 100644 djinit/templates/presets/predefined/api/urls.j2 delete mode 100644 djinit/templates/presets/predefined/api/v1/urls.j2 delete mode 100644 djinit/templates/presets/predefined/apps/generic/models.j2 create mode 100644 djinit/templates/presets/predefined/apps/generic/models.py-tpl delete mode 100644 djinit/templates/presets/predefined/apps/generic/serializers.j2 create mode 100644 djinit/templates/presets/predefined/apps/generic/serializers.py-tpl delete mode 100644 djinit/templates/presets/predefined/apps/generic/services.j2 create mode 100644 djinit/templates/presets/predefined/apps/generic/services.py-tpl delete mode 100644 djinit/templates/presets/predefined/apps/generic/tests.j2 create mode 100644 djinit/templates/presets/predefined/apps/generic/tests.py-tpl delete mode 100644 djinit/templates/presets/predefined/apps/generic/urls.j2 delete mode 100644 djinit/templates/presets/predefined/apps/generic/views.j2 create mode 100644 djinit/templates/presets/predefined/apps/generic/views.py-tpl rename djinit/templates/presets/predefined/apps/users/{models.j2 => models.py-tpl} (100%) rename djinit/templates/presets/predefined/apps/users/{serializers.j2 => serializers.py-tpl} (100%) rename djinit/templates/presets/predefined/apps/users/{services.j2 => services.py-tpl} (100%) rename djinit/templates/presets/predefined/apps/users/{tests.j2 => tests.py-tpl} (100%) delete mode 100644 djinit/templates/presets/predefined/apps/users/urls.j2 rename djinit/templates/presets/predefined/apps/users/{views.j2 => views.py-tpl} (100%) rename djinit/templates/presets/predefined/core/{exceptions.j2 => exceptions.py-tpl} (100%) rename djinit/templates/presets/predefined/core/middleware/{request_logger.j2 => request_logger.py-tpl} (100%) rename djinit/templates/presets/predefined/core/mixins/{timestamped_model.j2 => timestamped_model.py-tpl} (100%) delete mode 100644 djinit/templates/presets/predefined/core/utils/responses.j2 rename djinit/templates/presets/{unified/apps/core/utils/responses.py.j2 => predefined/core/utils/responses.py-tpl} (64%) rename djinit/templates/presets/unified/apps/core/{apps.j2 => apps.py-tpl} (100%) rename djinit/templates/presets/unified/apps/core/models/{__init__.py.j2 => __init__.py-tpl} (100%) rename djinit/templates/presets/unified/apps/core/models/{base.py.j2 => base.py-tpl} (100%) rename djinit/templates/presets/unified/apps/core/models/{mixins.py.j2 => mixins.py-tpl} (100%) rename djinit/templates/presets/unified/apps/core/utils/{__init__.py.j2 => __init__.py-tpl} (100%) rename djinit/templates/project/ci/{github_actions.j2 => github_actions-tpl} (94%) rename djinit/templates/project/ci/{gitlab_ci.j2 => gitlab_ci-tpl} (84%) rename djinit/templates/project/{env_sample.j2 => env_sample-tpl} (57%) rename djinit/templates/project/{gitignore.j2 => gitignore-tpl} (100%) delete mode 100644 djinit/templates/project/init.j2 rename djinit/templates/{components/migrations_init.j2 => project/init.py-tpl} (100%) rename djinit/templates/project/{justfile.j2 => justfile-tpl} (95%) rename djinit/templates/project/{manage_py.j2 => manage.py-tpl} (92%) rename djinit/templates/project/{procfile.j2 => procfile-tpl} (68%) rename djinit/templates/project/{pyproject_toml.j2 => pyproject.toml-tpl} (83%) rename djinit/templates/project/{readme.j2 => readme.md-tpl} (95%) rename djinit/templates/project/{requirements.j2 => requirements-tpl} (74%) create mode 100644 djinit/templates/project/runtime_txt-tpl delete mode 100644 djinit/templates/project/runtime_txt.j2 diff --git a/djinit/templates/components/admin.j2 b/djinit/templates/components/admin.py-tpl similarity index 100% rename from djinit/templates/components/admin.j2 rename to djinit/templates/components/admin.py-tpl diff --git a/djinit/templates/components/api_readme.j2 b/djinit/templates/components/api_readme.md-tpl similarity index 92% rename from djinit/templates/components/api_readme.j2 rename to djinit/templates/components/api_readme.md-tpl index 112cbe5..5d416ff 100644 --- a/djinit/templates/components/api_readme.j2 +++ b/djinit/templates/components/api_readme.md-tpl @@ -24,7 +24,7 @@ If you have a `User` model in `models/user.py`, create: ### 1. `api/user/serializers.py` ```python from rest_framework import serializers -from {{ module_name }}.models.user import User +from [[ module_name ]].models.user import User class UserSerializer(serializers.ModelSerializer): class Meta: @@ -35,7 +35,7 @@ class UserSerializer(serializers.ModelSerializer): ### 2. `api/user/views.py` ```python from rest_framework import viewsets -from {{ module_name }}.models.user import User +from [[ module_name ]].models.user import User from .serializers import UserSerializer class UserViewSet(viewsets.ModelViewSet): @@ -62,7 +62,7 @@ urlpatterns = [ from django.urls import path, include urlpatterns = [ - path('user/', include('{{ module_name }}.api.user.urls')), + path('user/', include('[[ module_name ]].api.user.urls')), # Add more API endpoints here ] ``` diff --git a/djinit/templates/components/apps.j2 b/djinit/templates/components/apps.j2 deleted file mode 100644 index bc3adcc..0000000 --- a/djinit/templates/components/apps.j2 +++ /dev/null @@ -1,8 +0,0 @@ -"""generated with djinit""" - -from django.apps import AppConfig - - -class {{ app_name|title }}Config(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = '{{ app_name }}' diff --git a/djinit/templates/components/apps.py-tpl b/djinit/templates/components/apps.py-tpl new file mode 100644 index 0000000..94f6a3d --- /dev/null +++ b/djinit/templates/components/apps.py-tpl @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class [[ app_name|title ]]Config(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = '[[ app_name ]]' diff --git a/djinit/templates/components/models.j2 b/djinit/templates/components/models.py-tpl similarity index 66% rename from djinit/templates/components/models.j2 rename to djinit/templates/components/models.py-tpl index 980c8e5..71a8362 100644 --- a/djinit/templates/components/models.j2 +++ b/djinit/templates/components/models.py-tpl @@ -1,5 +1,3 @@ -"""generated with djinit""" - from django.db import models # Create your models here. diff --git a/djinit/templates/components/models_readme.j2 b/djinit/templates/components/models_readme.md-tpl similarity index 98% rename from djinit/templates/components/models_readme.j2 rename to djinit/templates/components/models_readme.md-tpl index 867eebb..0bf247c 100644 --- a/djinit/templates/components/models_readme.j2 +++ b/djinit/templates/components/models_readme.md-tpl @@ -69,7 +69,7 @@ Create or update `admin/__init__.py`: ```python from django.contrib import admin -from {{ module_name }}.models import User +from [[ module_name ]].models import User @admin.register(User) class UserAdmin(admin.ModelAdmin): diff --git a/djinit/templates/components/routes.j2 b/djinit/templates/components/routes.j2 deleted file mode 100644 index 3831c00..0000000 --- a/djinit/templates/components/routes.j2 +++ /dev/null @@ -1,18 +0,0 @@ -""" -generated with djinit - -API routes for {{ app_name }} app. -""" - -from rest_framework.routers import DefaultRouter -from . import views - -# Create router instance -router = DefaultRouter() - -# Register viewsets with router -# Example: -# router.register(r'{{ app_name }}', views.{{ app_name|title }}ViewSet) - -# Get URL patterns -urlpatterns = router.urls diff --git a/djinit/templates/components/routes.py-tpl b/djinit/templates/components/routes.py-tpl new file mode 100644 index 0000000..37b00a9 --- /dev/null +++ b/djinit/templates/components/routes.py-tpl @@ -0,0 +1,8 @@ +from rest_framework.routers import DefaultRouter + +router = DefaultRouter() + +# Register your viewsets here +# router.register(r'endpoint', YourViewSet, basename='your-endpoint') + +urlpatterns = router.urls diff --git a/djinit/templates/components/serializers.j2 b/djinit/templates/components/serializers.j2 deleted file mode 100644 index e4b115d..0000000 --- a/djinit/templates/components/serializers.j2 +++ /dev/null @@ -1,14 +0,0 @@ -""" -generated with djinit -serializers for {{ app_name }} app. -""" - -from rest_framework import serializers - - -# Add your serializers here -# Example: -# class {{ app_name|title }}Serializer(serializers.ModelSerializer): -# class Meta: -# model = YourModel -# fields = '__all__' diff --git a/djinit/templates/components/serializers.py-tpl b/djinit/templates/components/serializers.py-tpl new file mode 100644 index 0000000..2774c36 --- /dev/null +++ b/djinit/templates/components/serializers.py-tpl @@ -0,0 +1,3 @@ +from rest_framework import serializers + +# Create your serializers here. diff --git a/djinit/templates/components/tests.j2 b/djinit/templates/components/tests.py-tpl similarity index 67% rename from djinit/templates/components/tests.j2 rename to djinit/templates/components/tests.py-tpl index 7fdd344..7ce503c 100644 --- a/djinit/templates/components/tests.j2 +++ b/djinit/templates/components/tests.py-tpl @@ -1,5 +1,3 @@ -"""generated with djinit""" - from django.test import TestCase # Create your tests here. diff --git a/djinit/templates/components/urls.j2 b/djinit/templates/components/urls.j2 deleted file mode 100644 index 501e65a..0000000 --- a/djinit/templates/components/urls.j2 +++ /dev/null @@ -1,11 +0,0 @@ -"""generated with djinit""" - -from django.urls import path -from . import views - -app_name = '{{ app_name }}' - -urlpatterns = [ - # Add your URL patterns here - # path('', views.index, name='index'), -] diff --git a/djinit/templates/components/views.j2 b/djinit/templates/components/views.py-tpl similarity index 68% rename from djinit/templates/components/views.j2 rename to djinit/templates/components/views.py-tpl index 7df6a0d..91ea44a 100644 --- a/djinit/templates/components/views.j2 +++ b/djinit/templates/components/views.py-tpl @@ -1,5 +1,3 @@ -"""generated with djinit""" - from django.shortcuts import render # Create your views here. diff --git a/djinit/templates/config/asgi.j2 b/djinit/templates/config/asgi.py-tpl similarity index 79% rename from djinit/templates/config/asgi.j2 rename to djinit/templates/config/asgi.py-tpl index 06cf14c..0c5c879 100644 --- a/djinit/templates/config/asgi.j2 +++ b/djinit/templates/config/asgi.py-tpl @@ -7,5 +7,5 @@ from django.core.asgi import get_asgi_application env = environ.Env() environ.Env.read_env() -os.environ.setdefault("DJANGO_SETTINGS_MODULE", env("DJANGO_SETTINGS_MODULE", default="{{ project_name }}.settings.production")) +os.environ.setdefault("DJANGO_SETTINGS_MODULE", env("DJANGO_SETTINGS_MODULE", default="[[ project_name ]].settings.production")) application = get_asgi_application() diff --git a/djinit/templates/config/settings/base.j2 b/djinit/templates/config/settings/base.py-tpl similarity index 94% rename from djinit/templates/config/settings/base.j2 rename to djinit/templates/config/settings/base.py-tpl index 25797c9..f33b399 100644 --- a/djinit/templates/config/settings/base.j2 +++ b/djinit/templates/config/settings/base.py-tpl @@ -29,8 +29,9 @@ THIRD_PARTY_APPS = [ ] USER_DEFINED_APPS = [ -{% for app in app_names %} "{{ app }}", -{% endfor %}] +# @LOOP app in app_names "[[ app ]]", +# @ENDLOOP +] BUILT_IN_APPS = [ "django.contrib.admin", @@ -56,7 +57,7 @@ MIDDLEWARE = [ "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = "{{ project_name }}.urls" +ROOT_URLCONF = "[[ project_name ]].urls" TEMPLATES = [ { @@ -73,7 +74,7 @@ TEMPLATES = [ }, ] -WSGI_APPLICATION = "{{ project_name }}.wsgi.application" +WSGI_APPLICATION = "[[ project_name ]].wsgi.application" # Password validation @@ -133,8 +134,8 @@ REST_FRAMEWORK = { # DRF Spectacular settings SPECTACULAR_SETTINGS = { - "TITLE": "{{ project_name }} API", - "DESCRIPTION": "API documentation for {{ project_name }}", + "TITLE": "[[ project_name ]] API", + "DESCRIPTION": "API documentation for [[ project_name ]]", "VERSION": "1.0.0", "SERVE_INCLUDE_SCHEMA": False, "COMPONENT_SPLIT_REQUEST": True, diff --git a/djinit/templates/config/settings/development.j2 b/djinit/templates/config/settings/development.py-tpl similarity index 97% rename from djinit/templates/config/settings/development.j2 rename to djinit/templates/config/settings/development.py-tpl index d787801..2e3c1b3 100644 --- a/djinit/templates/config/settings/development.j2 +++ b/djinit/templates/config/settings/development.py-tpl @@ -2,7 +2,7 @@ from .base import * -SECRET_KEY = "{{ secret_key }}" +SECRET_KEY = "[[ secret_key ]]" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True diff --git a/djinit/templates/config/settings/production.j2 b/djinit/templates/config/settings/production.py-tpl similarity index 92% rename from djinit/templates/config/settings/production.j2 rename to djinit/templates/config/settings/production.py-tpl index a2ab0f6..72d0c42 100644 --- a/djinit/templates/config/settings/production.j2 +++ b/djinit/templates/config/settings/production.py-tpl @@ -8,29 +8,29 @@ SECRET_KEY = env('SECRET_KEY') ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=[]) # Database -{% if use_database_url %} +# @IF use_database_url # Using dj_database_url (recommended for production) DATABASES = { 'default': env.db('DATABASE_URL') } -{% else %} +# @ELSE # Using individual database parameters DATABASES = { 'default': { - {% if database_type == 'mysql' %} + # @IF database_type == 'mysql' 'ENGINE': 'django.db.backends.mysql', 'PORT': env('DB_PORT', default='3306'), - {% else %} + # @ELSE 'ENGINE': 'django.db.backends.postgresql', 'PORT': env('DB_PORT', default='5432'), - {% endif %} + # @ENDIF 'NAME': env('DB_NAME'), 'USER': env('DB_USER'), 'PASSWORD': env('DB_PASSWORD'), 'HOST': env('DB_HOST'), } } -{% endif %} +# @ENDIF # CORS settings for production # Filter out empty strings from FRONTEND_URL diff --git a/djinit/templates/config/urls.py-tpl b/djinit/templates/config/urls.py-tpl new file mode 100644 index 0000000..574294f --- /dev/null +++ b/djinit/templates/config/urls.py-tpl @@ -0,0 +1,103 @@ +# @IF url_type == 'project' +"""generated with djinit""" + +from django.contrib import admin +from django.urls import path +# @IF include_api or include_apps +from django.urls import include +# @ENDIF +# @IF include_api +from django.conf import settings +from drf_spectacular.views import ( + SpectacularAPIView, + SpectacularSwaggerView, +) +from rest_framework_simplejwt.views import ( + TokenObtainPairView, + TokenRefreshView, + TokenBlacklistView, +) +# @ENDIF + +urlpatterns = [ + path("admin/", admin.site.urls), +# @IF include_api + # JWT tokens + path("token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), + path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), + path("token/blacklist/", TokenBlacklistView.as_view(), name="token_blacklist"), +# @ENDIF +# @IF include_api and comment_out_api_url + # path("api/", include("[[ api_module ]].urls")), +# @ENDIF +# @IF include_api and not comment_out_api_url + path("api/", include("[[ api_module ]].urls")), +# @ENDIF +# @IF include_apps + # App URLs +# @LOOP app in app_names + path("", include("[[ app ]].urls")), +# @ENDLOOP +# @ENDIF +] +# @IF include_api + +# Don't show schema in production +if settings.DEBUG: + urlpatterns += [ + path("schema/", SpectacularAPIView.as_view(), name="schema"), + path("docs/", SpectacularSwaggerView.as_view(url_name="schema")), + ] +# @ENDIF +# @ENDIF +# @IF url_type == 'api_root' +from django.urls import include, path + +app_name = "[[ app_name ]]" + +urlpatterns = [ + path("[[ version ]]/", include("[[ api_module ]].[[ version ]].urls")), +] +# @ENDIF +# @IF url_type == 'api_version' +from django.urls import include, path + +app_name = "[[ app_name ]]" + +urlpatterns = [ +# @LOOP app in app_list + path("[[ app ]]/", include("[[ app_module ]].[[ app ]].urls")), +# @ENDLOOP +] +# @ENDIF +# @IF url_type == 'drf_router' +from rest_framework.routers import DefaultRouter +# @IF has_viewset +from [[ app_module ]].views.[[ view_file ]] import [[ viewset_name ]] +# @ENDIF +# @IF has_app_name + +app_name = "[[ app_name ]]" +# @ENDIF + +router = DefaultRouter() +# @IF has_viewset +router.register(r"[[ router_prefix ]]", [[ viewset_name ]], basename="[[ basename ]]") +# @ENDIF + +urlpatterns = [ +# @IF has_include + path("", include(router.urls)), +# @ENDIF +] +# @IF not has_include +urlpatterns = router.urls +# @ENDIF +# @ENDIF +# @IF url_type == 'component' +from django.urls import path + +urlpatterns = [ + # Add your URL patterns here +] +# @ENDIF diff --git a/djinit/templates/config/urls/base.j2 b/djinit/templates/config/urls/base.j2 deleted file mode 100644 index ab41ddb..0000000 --- a/djinit/templates/config/urls/base.j2 +++ /dev/null @@ -1,8 +0,0 @@ -"""generated with djinit""" - -from django.contrib import admin -from django.urls import path - -urlpatterns = [ - path('admin/', admin.site.urls), -] diff --git a/djinit/templates/config/urls/with_api.j2 b/djinit/templates/config/urls/with_api.j2 deleted file mode 100644 index d0f0202..0000000 --- a/djinit/templates/config/urls/with_api.j2 +++ /dev/null @@ -1,30 +0,0 @@ -"""generated with djinit""" - -from django.contrib import admin -from django.urls import path, include -from django.conf import settings -from drf_spectacular.views import ( - SpectacularAPIView, - SpectacularSwaggerView, -) -from rest_framework_simplejwt.views import ( - TokenObtainPairView, - TokenRefreshView, - TokenBlacklistView, -) - -urlpatterns = [ - path("admin/", admin.site.urls), - # JWT tokens - path("token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), - path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), - path("token/blacklist/", TokenBlacklistView.as_view(), name="token_blacklist"), - {% if comment_out_api_url %}# {% endif %}path("api/", include("{{ api_module }}.urls")), -] - -# Don't show schema in production -if settings.DEBUG: - urlpatterns += [ - path("schema/", SpectacularAPIView.as_view(), name="schema"), - path("docs/", SpectacularSwaggerView.as_view(url_name="schema")), - ] diff --git a/djinit/templates/config/urls/with_apps.j2 b/djinit/templates/config/urls/with_apps.j2 deleted file mode 100644 index a299544..0000000 --- a/djinit/templates/config/urls/with_apps.j2 +++ /dev/null @@ -1,31 +0,0 @@ -"""generated with djinit""" - -from django.contrib import admin -from django.urls import path, include -from django.conf import settings -from drf_spectacular.views import ( - SpectacularAPIView, - SpectacularSwaggerView, -) -from rest_framework_simplejwt.views import ( - TokenObtainPairView, - TokenRefreshView, - TokenBlacklistView, -) - -urlpatterns = [ - path("admin/", admin.site.urls), - # JWT tokens - path("token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), - path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), - path("token/blacklist/", TokenBlacklistView.as_view(), name="token_blacklist"), - # App URLs -{% if comment_out_api_url %}# {% endif %} {% for app in app_names %} path("", include("{{ app }}.urls")), -{% endfor %}] - -# Don't show schema in production -if settings.DEBUG: - urlpatterns += [ - path("schema/", SpectacularAPIView.as_view(), name="schema"), - path("docs/", SpectacularSwaggerView.as_view(url_name="schema")), - ] diff --git a/djinit/templates/config/wsgi.j2 b/djinit/templates/config/wsgi.py-tpl similarity index 79% rename from djinit/templates/config/wsgi.j2 rename to djinit/templates/config/wsgi.py-tpl index de26d9b..421456d 100644 --- a/djinit/templates/config/wsgi.j2 +++ b/djinit/templates/config/wsgi.py-tpl @@ -7,6 +7,6 @@ from django.core.wsgi import get_wsgi_application env = environ.Env() environ.Env.read_env() -os.environ.setdefault("DJANGO_SETTINGS_MODULE", env("DJANGO_SETTINGS_MODULE", default="{{ project_name }}.settings.production")) +os.environ.setdefault("DJANGO_SETTINGS_MODULE", env("DJANGO_SETTINGS_MODULE", default="[[ project_name ]].settings.production")) application = get_wsgi_application() diff --git a/djinit/templates/presets/predefined/api/urls.j2 b/djinit/templates/presets/predefined/api/urls.j2 deleted file mode 100644 index 51e3dfb..0000000 --- a/djinit/templates/presets/predefined/api/urls.j2 +++ /dev/null @@ -1,7 +0,0 @@ -from django.urls import include, path - -app_name = "api" - -urlpatterns = [ - path("v1/", include("api.v1.urls")), -] diff --git a/djinit/templates/presets/predefined/api/v1/urls.j2 b/djinit/templates/presets/predefined/api/v1/urls.j2 deleted file mode 100644 index 7a0d9a8..0000000 --- a/djinit/templates/presets/predefined/api/v1/urls.j2 +++ /dev/null @@ -1,7 +0,0 @@ -from django.urls import include, path - -app_name = "v1" - -urlpatterns = [ - path("users/", include("apps.users.urls")), -] diff --git a/djinit/templates/presets/predefined/apps/generic/models.j2 b/djinit/templates/presets/predefined/apps/generic/models.j2 deleted file mode 100644 index 9f99a46..0000000 --- a/djinit/templates/presets/predefined/apps/generic/models.j2 +++ /dev/null @@ -1,8 +0,0 @@ -from django.db import models - - -class {{ model_class_name }}(models.Model): - """Generated model for {{ app_name }} app.""" - - # Add fields here - pass diff --git a/djinit/templates/presets/predefined/apps/generic/models.py-tpl b/djinit/templates/presets/predefined/apps/generic/models.py-tpl new file mode 100644 index 0000000..bbae956 --- /dev/null +++ b/djinit/templates/presets/predefined/apps/generic/models.py-tpl @@ -0,0 +1,18 @@ +from django.db import models + + +class [[ model_class_name ]](models.Model): + """[[ model_class_name ]] model.""" + + # Add your fields here + name = models.CharField(max_length=255) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + verbose_name = "[[ model_class_name ]]" + verbose_name_plural = "[[ model_class_name ]]s" + ordering = ["-created_at"] + + def __str__(self): + return self.name diff --git a/djinit/templates/presets/predefined/apps/generic/serializers.j2 b/djinit/templates/presets/predefined/apps/generic/serializers.j2 deleted file mode 100644 index 86f1b45..0000000 --- a/djinit/templates/presets/predefined/apps/generic/serializers.j2 +++ /dev/null @@ -1,9 +0,0 @@ -from rest_framework import serializers - -from {{ app_module }}.models.{{ app_name }} import {{ model_class_name }} - - -class {{ model_class_name }}Serializer(serializers.ModelSerializer): - class Meta: - model = {{ model_class_name }} - fields = "__all__" diff --git a/djinit/templates/presets/predefined/apps/generic/serializers.py-tpl b/djinit/templates/presets/predefined/apps/generic/serializers.py-tpl new file mode 100644 index 0000000..30b7189 --- /dev/null +++ b/djinit/templates/presets/predefined/apps/generic/serializers.py-tpl @@ -0,0 +1,11 @@ +from rest_framework import serializers +from [[ app_module ]].models.[[ app_name ]] import [[ model_class_name ]] + + +class [[ model_class_name ]]Serializer(serializers.ModelSerializer): + """Serializer for [[ model_class_name ]] model.""" + + class Meta: + model = [[ model_class_name ]] + fields = "__all__" + read_only_fields = ["id", "created_at", "updated_at"] diff --git a/djinit/templates/presets/predefined/apps/generic/services.j2 b/djinit/templates/presets/predefined/apps/generic/services.j2 deleted file mode 100644 index 2203fb8..0000000 --- a/djinit/templates/presets/predefined/apps/generic/services.j2 +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Optional - -from {{ app_module }}.models.{{ app_name }} import {{ model_class_name }} - - -def get_{{ app_name }}_by_id(object_id: int) -> Optional[{{ model_class_name }}]: - try: - return {{ model_class_name }}.objects.get(id=object_id) - except {{ model_class_name }}.DoesNotExist: - return None diff --git a/djinit/templates/presets/predefined/apps/generic/services.py-tpl b/djinit/templates/presets/predefined/apps/generic/services.py-tpl new file mode 100644 index 0000000..de45859 --- /dev/null +++ b/djinit/templates/presets/predefined/apps/generic/services.py-tpl @@ -0,0 +1,36 @@ +from [[ app_module ]].models.[[ app_name ]] import [[ model_class_name ]] + + +class [[ model_class_name ]]Service: + """Service class for [[ model_class_name ]] business logic.""" + + @staticmethod + def get_all(): + """Get all [[ model_class_name ]] instances.""" + return [[ model_class_name ]].objects.all() + + @staticmethod + def get_by_id(id): + """Get [[ model_class_name ]] by ID.""" + try: + return [[ model_class_name ]].objects.get(id=id) + except [[ model_class_name ]].DoesNotExist: + return None + + @staticmethod + def create(data): + """Create a new [[ model_class_name ]] instance.""" + return [[ model_class_name ]].objects.create(**data) + + @staticmethod + def update(instance, data): + """Update an existing [[ model_class_name ]] instance.""" + for key, value in data.items(): + setattr(instance, key, value) + instance.save() + return instance + + @staticmethod + def delete(instance): + """Delete a [[ model_class_name ]] instance.""" + instance.delete() diff --git a/djinit/templates/presets/predefined/apps/generic/tests.j2 b/djinit/templates/presets/predefined/apps/generic/tests.j2 deleted file mode 100644 index 41fc906..0000000 --- a/djinit/templates/presets/predefined/apps/generic/tests.j2 +++ /dev/null @@ -1,12 +0,0 @@ -import pytest -from django.urls import reverse -from rest_framework.test import APIClient - - -@pytest.mark.django_db -def test_{{ app_name }}_list_empty(): - client = APIClient() - url = reverse("v1:{{ app_name }}-list") - response = client.get(url) - assert response.status_code == 200 - assert response.json() == [] diff --git a/djinit/templates/presets/predefined/apps/generic/tests.py-tpl b/djinit/templates/presets/predefined/apps/generic/tests.py-tpl new file mode 100644 index 0000000..8dc7a7e --- /dev/null +++ b/djinit/templates/presets/predefined/apps/generic/tests.py-tpl @@ -0,0 +1,55 @@ +from rest_framework.test import APITestCase +from rest_framework import status +from django.contrib.auth import get_user_model + +from [[ app_module ]].models.[[ app_name ]] import [[ model_class_name ]] + +User = get_user_model() + + +class [[ model_class_name ]]APITestCase(APITestCase): + """Test cases for [[ model_class_name ]] API endpoints.""" + + def setUp(self): + """Set up test data.""" + self.user = User.objects.create_user( + username="testuser", password="testpass123" + ) + self.client.force_authenticate(user=self.user) + self.test_data = {"name": "Test [[ model_class_name ]]"} + + def test_create_[[ app_name ]](self): + """Test creating a [[ model_class_name ]].""" + response = self.client.post("/api/v1/[[ app_name ]]/", self.test_data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual([[ model_class_name ]].objects.count(), 1) + + def test_list_[[ app_name ]]s(self): + """Test listing all [[ model_class_name ]]s.""" + [[ model_class_name ]].objects.create(**self.test_data) + response = self.client.get("/api/v1/[[ app_name ]]/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 1) + + def test_retrieve_[[ app_name ]](self): + """Test retrieving a single [[ model_class_name ]].""" + instance = [[ model_class_name ]].objects.create(**self.test_data) + response = self.client.get(f"/api/v1/[[ app_name ]]/{instance.id}/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["name"], self.test_data["name"]) + + def test_update_[[ app_name ]](self): + """Test updating a [[ model_class_name ]].""" + instance = [[ model_class_name ]].objects.create(**self.test_data) + updated_data = {"name": "Updated [[ model_class_name ]]"} + response = self.client.patch(f"/api/v1/[[ app_name ]]/{instance.id}/", updated_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + instance.refresh_from_db() + self.assertEqual(instance.name, updated_data["name"]) + + def test_delete_[[ app_name ]](self): + """Test deleting a [[ model_class_name ]].""" + instance = [[ model_class_name ]].objects.create(**self.test_data) + response = self.client.delete(f"/api/v1/[[ app_name ]]/{instance.id}/") + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual([[ model_class_name ]].objects.count(), 0) diff --git a/djinit/templates/presets/predefined/apps/generic/urls.j2 b/djinit/templates/presets/predefined/apps/generic/urls.j2 deleted file mode 100644 index caec1a6..0000000 --- a/djinit/templates/presets/predefined/apps/generic/urls.j2 +++ /dev/null @@ -1,14 +0,0 @@ -from django.urls import include, path -from rest_framework.routers import DefaultRouter - -from {{ app_module }}.views.{{ app_name }}_view import {{ model_class_name }}ViewSet - - -app_name = "{{ app_name }}" - -router = DefaultRouter() -router.register(r"{{ app_name }}", {{ model_class_name }}ViewSet, basename="{{ app_name }}") - -urlpatterns = [ - path("", include(router.urls)), -] diff --git a/djinit/templates/presets/predefined/apps/generic/views.j2 b/djinit/templates/presets/predefined/apps/generic/views.j2 deleted file mode 100644 index 5976564..0000000 --- a/djinit/templates/presets/predefined/apps/generic/views.j2 +++ /dev/null @@ -1,9 +0,0 @@ -from rest_framework import viewsets - -from {{ app_module }}.models.{{ app_name }} import {{ model_class_name }} -from {{ app_module }}.serializers.{{ app_name }}_serializer import {{ model_class_name }}Serializer - - -class {{ model_class_name }}ViewSet(viewsets.ModelViewSet): - queryset = {{ model_class_name }}.objects.all() - serializer_class = {{ model_class_name }}Serializer diff --git a/djinit/templates/presets/predefined/apps/generic/views.py-tpl b/djinit/templates/presets/predefined/apps/generic/views.py-tpl new file mode 100644 index 0000000..ef85cf5 --- /dev/null +++ b/djinit/templates/presets/predefined/apps/generic/views.py-tpl @@ -0,0 +1,62 @@ +from rest_framework import viewsets, status +from rest_framework.response import Response +from rest_framework.permissions import IsAuthenticated + +from [[ app_module ]].models.[[ app_name ]] import [[ model_class_name ]] +from [[ app_module ]].serializers.[[ app_name ]]_serializer import [[ model_class_name ]]Serializer +from [[ app_module ]].services.[[ app_name ]]_service import [[ model_class_name ]]Service + + +class [[ model_class_name ]]ViewSet(viewsets.ModelViewSet): + """ViewSet for [[ model_class_name ]] CRUD operations.""" + + queryset = [[ model_class_name ]].objects.all() + serializer_class = [[ model_class_name ]]Serializer + permission_classes = [IsAuthenticated] + + def list(self, request): + """List all [[ model_class_name ]] instances.""" + instances = [[ model_class_name ]]Service.get_all() + serializer = self.get_serializer(instances, many=True) + return Response(serializer.data) + + def retrieve(self, request, pk=None): + """Retrieve a single [[ model_class_name ]] instance.""" + instance = [[ model_class_name ]]Service.get_by_id(pk) + if not instance: + return Response( + {"error": "[[ model_class_name ]] not found"}, status=status.HTTP_404_NOT_FOUND + ) + serializer = self.get_serializer(instance) + return Response(serializer.data) + + def create(self, request): + """Create a new [[ model_class_name ]] instance.""" + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + instance = [[ model_class_name ]]Service.create(serializer.validated_data) + return Response( + self.get_serializer(instance).data, status=status.HTTP_201_CREATED + ) + + def update(self, request, pk=None): + """Update an existing [[ model_class_name ]] instance.""" + instance = [[ model_class_name ]]Service.get_by_id(pk) + if not instance: + return Response( + {"error": "[[ model_class_name ]] not found"}, status=status.HTTP_404_NOT_FOUND + ) + serializer = self.get_serializer(instance, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + updated_instance = [[ model_class_name ]]Service.update(instance, serializer.validated_data) + return Response(self.get_serializer(updated_instance).data) + + def destroy(self, request, pk=None): + """Delete a [[ model_class_name ]] instance.""" + instance = [[ model_class_name ]]Service.get_by_id(pk) + if not instance: + return Response( + {"error": "[[ model_class_name ]] not found"}, status=status.HTTP_404_NOT_FOUND + ) + [[ model_class_name ]]Service.delete(instance) + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/djinit/templates/presets/predefined/apps/users/models.j2 b/djinit/templates/presets/predefined/apps/users/models.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/apps/users/models.j2 rename to djinit/templates/presets/predefined/apps/users/models.py-tpl diff --git a/djinit/templates/presets/predefined/apps/users/serializers.j2 b/djinit/templates/presets/predefined/apps/users/serializers.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/apps/users/serializers.j2 rename to djinit/templates/presets/predefined/apps/users/serializers.py-tpl diff --git a/djinit/templates/presets/predefined/apps/users/services.j2 b/djinit/templates/presets/predefined/apps/users/services.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/apps/users/services.j2 rename to djinit/templates/presets/predefined/apps/users/services.py-tpl diff --git a/djinit/templates/presets/predefined/apps/users/tests.j2 b/djinit/templates/presets/predefined/apps/users/tests.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/apps/users/tests.j2 rename to djinit/templates/presets/predefined/apps/users/tests.py-tpl diff --git a/djinit/templates/presets/predefined/apps/users/urls.j2 b/djinit/templates/presets/predefined/apps/users/urls.j2 deleted file mode 100644 index 08a6fb4..0000000 --- a/djinit/templates/presets/predefined/apps/users/urls.j2 +++ /dev/null @@ -1,14 +0,0 @@ -from django.urls import include, path -from rest_framework.routers import DefaultRouter - -from apps.users.views.user_view import UserViewSet - - -app_name = "users" - -router = DefaultRouter() -router.register(r"users", UserViewSet, basename="users") - -urlpatterns = [ - path("", include(router.urls)), -] diff --git a/djinit/templates/presets/predefined/apps/users/views.j2 b/djinit/templates/presets/predefined/apps/users/views.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/apps/users/views.j2 rename to djinit/templates/presets/predefined/apps/users/views.py-tpl diff --git a/djinit/templates/presets/predefined/core/exceptions.j2 b/djinit/templates/presets/predefined/core/exceptions.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/core/exceptions.j2 rename to djinit/templates/presets/predefined/core/exceptions.py-tpl diff --git a/djinit/templates/presets/predefined/core/middleware/request_logger.j2 b/djinit/templates/presets/predefined/core/middleware/request_logger.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/core/middleware/request_logger.j2 rename to djinit/templates/presets/predefined/core/middleware/request_logger.py-tpl diff --git a/djinit/templates/presets/predefined/core/mixins/timestamped_model.j2 b/djinit/templates/presets/predefined/core/mixins/timestamped_model.py-tpl similarity index 100% rename from djinit/templates/presets/predefined/core/mixins/timestamped_model.j2 rename to djinit/templates/presets/predefined/core/mixins/timestamped_model.py-tpl diff --git a/djinit/templates/presets/predefined/core/utils/responses.j2 b/djinit/templates/presets/predefined/core/utils/responses.j2 deleted file mode 100644 index bae79a1..0000000 --- a/djinit/templates/presets/predefined/core/utils/responses.j2 +++ /dev/null @@ -1,9 +0,0 @@ -from rest_framework.response import Response - - -def success(data=None, status_code=200): - return Response({"success": True, "data": data}, status=status_code) - - -def error(message, status_code=400): - return Response({"success": False, "message": message}, status=status_code) diff --git a/djinit/templates/presets/unified/apps/core/utils/responses.py.j2 b/djinit/templates/presets/predefined/core/utils/responses.py-tpl similarity index 64% rename from djinit/templates/presets/unified/apps/core/utils/responses.py.j2 rename to djinit/templates/presets/predefined/core/utils/responses.py-tpl index 929c2f6..f4b5269 100644 --- a/djinit/templates/presets/unified/apps/core/utils/responses.py.j2 +++ b/djinit/templates/presets/predefined/core/utils/responses.py-tpl @@ -1,13 +1,17 @@ +# @IF include_header """generated with djinit""" +# @ENDIF from rest_framework.response import Response def success(data=None, status_code=200): - """Return a successful response.""" +# @IF include_docstrings """Return a successful response.""" +# @ENDIF return Response({"success": True, "data": data}, status=status_code) def error(message, status_code=400): - """Return an error response.""" +# @IF include_docstrings """Return an error response.""" +# @ENDIF return Response({"success": False, "message": message}, status=status_code) diff --git a/djinit/templates/presets/unified/apps/core/apps.j2 b/djinit/templates/presets/unified/apps/core/apps.py-tpl similarity index 100% rename from djinit/templates/presets/unified/apps/core/apps.j2 rename to djinit/templates/presets/unified/apps/core/apps.py-tpl diff --git a/djinit/templates/presets/unified/apps/core/models/__init__.py.j2 b/djinit/templates/presets/unified/apps/core/models/__init__.py-tpl similarity index 100% rename from djinit/templates/presets/unified/apps/core/models/__init__.py.j2 rename to djinit/templates/presets/unified/apps/core/models/__init__.py-tpl diff --git a/djinit/templates/presets/unified/apps/core/models/base.py.j2 b/djinit/templates/presets/unified/apps/core/models/base.py-tpl similarity index 100% rename from djinit/templates/presets/unified/apps/core/models/base.py.j2 rename to djinit/templates/presets/unified/apps/core/models/base.py-tpl diff --git a/djinit/templates/presets/unified/apps/core/models/mixins.py.j2 b/djinit/templates/presets/unified/apps/core/models/mixins.py-tpl similarity index 100% rename from djinit/templates/presets/unified/apps/core/models/mixins.py.j2 rename to djinit/templates/presets/unified/apps/core/models/mixins.py-tpl diff --git a/djinit/templates/presets/unified/apps/core/utils/__init__.py.j2 b/djinit/templates/presets/unified/apps/core/utils/__init__.py-tpl similarity index 100% rename from djinit/templates/presets/unified/apps/core/utils/__init__.py.j2 rename to djinit/templates/presets/unified/apps/core/utils/__init__.py-tpl diff --git a/djinit/templates/project/ci/github_actions.j2 b/djinit/templates/project/ci/github_actions-tpl similarity index 94% rename from djinit/templates/project/ci/github_actions.j2 rename to djinit/templates/project/ci/github_actions-tpl index 7be2bd5..5217107 100644 --- a/djinit/templates/project/ci/github_actions.j2 +++ b/djinit/templates/project/ci/github_actions-tpl @@ -62,7 +62,7 @@ jobs: - name: Run Django tests env: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost DB_NAME: test_db @@ -76,7 +76,7 @@ jobs: - name: Check migrations env: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost DB_NAME: test_db diff --git a/djinit/templates/project/ci/gitlab_ci.j2 b/djinit/templates/project/ci/gitlab_ci-tpl similarity index 84% rename from djinit/templates/project/ci/gitlab_ci.j2 rename to djinit/templates/project/ci/gitlab_ci-tpl index ff6ef5b..3d3bc61 100644 --- a/djinit/templates/project/ci/gitlab_ci.j2 +++ b/djinit/templates/project/ci/gitlab_ci-tpl @@ -1,4 +1,4 @@ -# GitLab CI/CD configuration for {{ project_name }} +# GitLab CI/CD configuration for [[ project_name ]] stages: - test @@ -36,7 +36,7 @@ test: stage: test image: python:3.13 variables: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost script: @@ -52,7 +52,7 @@ test:python310: stage: test image: python:3.10 variables: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost script: @@ -69,7 +69,7 @@ test:python311: stage: test image: python:3.11 variables: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost script: @@ -86,7 +86,7 @@ test:python312: stage: test image: python:3.12 variables: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost script: @@ -103,7 +103,7 @@ test:python313: stage: test image: python:3.13 variables: - DJANGO_SETTINGS_MODULE: {{ module_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development SECRET_KEY: test-secret-key-for-ci ALLOWED_HOSTS: localhost script: @@ -121,7 +121,7 @@ security: stage: security image: python:3.13 variables: - DJANGO_SETTINGS_MODULE: {{ project_name }}.settings.development + DJANGO_SETTINGS_MODULE: [[ project_name ]].settings.development SECRET_KEY: test-secret-key-for-ci script: - pip install uv diff --git a/djinit/templates/project/env_sample.j2 b/djinit/templates/project/env_sample-tpl similarity index 57% rename from djinit/templates/project/env_sample.j2 rename to djinit/templates/project/env_sample-tpl index f5f2388..65d6da7 100644 --- a/djinit/templates/project/env_sample.j2 +++ b/djinit/templates/project/env_sample-tpl @@ -1,23 +1,23 @@ # Django settings -DJANGO_SETTINGS_MODULE={{ project_name }}.settings.development +DJANGO_SETTINGS_MODULE=[[ project_name ]].settings.development SECRET_KEY= your-secret-key ALLOWED_HOSTS=api.your-domain.com,www.your-domain.com -{% if use_database_url %} +# @IF use_database_url # Database URL (recommended for production) -{% if database_type == 'mysql' %} -DATABASE_URL=mysql://user:password@localhost:3306/{{ project_name }} -{% else %} -DATABASE_URL=postgres://user:password@localhost:5432/{{ project_name }} -{% endif %} -{% else %} +# @IF database_type == 'mysql' +DATABASE_URL=mysql://user:password@localhost:3306/[[ project_name ]] +# @ELSE +DATABASE_URL=postgres://user:password@localhost:5432/[[ project_name ]] +# @ENDIF +# @ELSE # Database (individual parameters) DB_NAME= DB_USER= DB_PASSWORD= DB_HOST= DB_PORT= -{% endif %} +# @ENDIF # Frontend URL FRONTEND_URL=http://frontend.your-domain.com diff --git a/djinit/templates/project/gitignore.j2 b/djinit/templates/project/gitignore-tpl similarity index 100% rename from djinit/templates/project/gitignore.j2 rename to djinit/templates/project/gitignore-tpl diff --git a/djinit/templates/project/init.j2 b/djinit/templates/project/init.j2 deleted file mode 100644 index e69de29..0000000 diff --git a/djinit/templates/components/migrations_init.j2 b/djinit/templates/project/init.py-tpl similarity index 100% rename from djinit/templates/components/migrations_init.j2 rename to djinit/templates/project/init.py-tpl diff --git a/djinit/templates/project/justfile.j2 b/djinit/templates/project/justfile-tpl similarity index 95% rename from djinit/templates/project/justfile.j2 rename to djinit/templates/project/justfile-tpl index b5e511d..127e77d 100644 --- a/djinit/templates/project/justfile.j2 +++ b/djinit/templates/project/justfile-tpl @@ -1,4 +1,4 @@ -# Justfile for {{ project_name }} +# Justfile for [[ project_name ]] # Task runner for Django development # Install just: https://github.com/casey/just @@ -108,15 +108,15 @@ dbshell: # Start production server with gunicorn server: - uv run gunicorn {{ project_name }}.wsgi:application --bind 0.0.0.0:8000 + uv run gunicorn [[ project_name ]].wsgi:application --bind 0.0.0.0:8000 # Start production server with gunicorn workers server-prod WORKERS="4": - uv run gunicorn {{ project_name }}.wsgi:application --bind 0.0.0.0:8000 --workers {{ '{{' }}WORKERS{{ '}}' }} + uv run gunicorn [[ project_name ]].wsgi:application --bind 0.0.0.0:8000 --workers {{ '{{' }}WORKERS{{ '}}' }} # Start production server with gunicorn and reload on file changes server-watch: - uv run gunicorn {{ project_name }}.wsgi:application --bind 0.0.0.0:8000 --reload + uv run gunicorn [[ project_name ]].wsgi:application --bind 0.0.0.0:8000 --reload # Clean Python cache files clean: diff --git a/djinit/templates/project/manage_py.j2 b/djinit/templates/project/manage.py-tpl similarity index 92% rename from djinit/templates/project/manage_py.j2 rename to djinit/templates/project/manage.py-tpl index b6a20b7..ba6f5c7 100644 --- a/djinit/templates/project/manage_py.j2 +++ b/djinit/templates/project/manage.py-tpl @@ -11,7 +11,7 @@ import environ def main(): """Run administrative tasks.""" - os.environ.setdefault("DJANGO_SETTINGS_MODULE", os.getenv("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings.production")) + os.environ.setdefault("DJANGO_SETTINGS_MODULE", os.getenv("DJANGO_SETTINGS_MODULE", "[[ project_name ]].settings.production")) try: from django.core.management import execute_from_command_line diff --git a/djinit/templates/project/procfile.j2 b/djinit/templates/project/procfile-tpl similarity index 68% rename from djinit/templates/project/procfile.j2 rename to djinit/templates/project/procfile-tpl index bb2c0db..fc01178 100644 --- a/djinit/templates/project/procfile.j2 +++ b/djinit/templates/project/procfile-tpl @@ -1,20 +1,20 @@ -# Procfile for {{ project_name }} +# Procfile for [[ project_name ]] # Used for deploying to PaaS platforms like Heroku, Railway, Render, etc. # Web server process (using Gunicorn) # Adjust workers based on your needs: (2 x CPU cores) + 1 -web: gunicorn {{ project_name }}.wsgi:application --bind 0.0.0.0:$PORT --workers 2 --timeout 120 --access-logfile - --error-logfile - --log-level info +web: gunicorn [[ project_name ]].wsgi:application --bind 0.0.0.0:$PORT --workers 2 --timeout 120 --access-logfile - --error-logfile - --log-level info # Alternative web server configurations (uncomment to use): -# web: gunicorn {{ project_name }}.wsgi:application --bind 0.0.0.0:$PORT --workers 4 --threads 2 --timeout 120 -# web: gunicorn {{ project_name }}.wsgi:application --bind 0.0.0.0:$PORT --workers 2 --worker-class gevent --worker-connections 1000 --timeout 120 +# web: gunicorn [[ project_name ]].wsgi:application --bind 0.0.0.0:$PORT --workers 4 --threads 2 --timeout 120 +# web: gunicorn [[ project_name ]].wsgi:application --bind 0.0.0.0:$PORT --workers 2 --worker-class gevent --worker-connections 1000 --timeout 120 # Release task (runs migrations before deployment) release: python manage.py migrate --noinput && python manage.py collectstatic --noinput # Uncomment below to run scheduled tasks (if using Celery) -# worker: celery -A {{ project_name }} worker --loglevel=info -# beat: celery -A {{ project_name }} beat --loglevel=info +# worker: celery -A [[ project_name ]] worker --loglevel=info +# beat: celery -A [[ project_name ]] beat --loglevel=info # Development server (for local testing with Foreman/Overmind) # web: python manage.py runserver 0.0.0.0:$PORT diff --git a/djinit/templates/project/pyproject_toml.j2 b/djinit/templates/project/pyproject.toml-tpl similarity index 83% rename from djinit/templates/project/pyproject_toml.j2 rename to djinit/templates/project/pyproject.toml-tpl index 28e3942..e9e49a3 100644 --- a/djinit/templates/project/pyproject_toml.j2 +++ b/djinit/templates/project/pyproject.toml-tpl @@ -1,5 +1,5 @@ [project] -name = "{{ package_name }}" +name = "[[ package_name ]]" version = "0.1.0" description = "" readme = "README.md" @@ -14,8 +14,12 @@ dependencies = [ "drf-spectacular", "django-cors-headers", "whitenoise", +# @IF database_type == 'mysql' "mysqlclient", +# @ENDIF +# @IF database_type == 'postgresql' "psycopg2-binary", +# @ENDIF "gunicorn", ] @@ -39,4 +43,4 @@ ignore = [ ] [tool.ruff.lint.isort] -known-first-party = ["{{ project_name }}"] +known-first-party = ["[[ project_name ]]"] diff --git a/djinit/templates/project/readme.j2 b/djinit/templates/project/readme.md-tpl similarity index 95% rename from djinit/templates/project/readme.j2 rename to djinit/templates/project/readme.md-tpl index 1aac23c..c107ade 100644 --- a/djinit/templates/project/readme.j2 +++ b/djinit/templates/project/readme.md-tpl @@ -1,4 +1,4 @@ -# {{ project_name }} +# [[ project_name ]] A Django project folder structure is generated with [djinitx/djinit/dj](https://github.com/S4NKALP/djinit). @@ -71,9 +71,9 @@ Run `just` to see all available commands, including: ## Project Structure ``` -{% if predefined_structure %} -{{ project_name }}/ -├── {{ module_name }}/ +# @IF predefined_structure +[[ project_name ]]/ +├── [[ module_name ]]/ │ ├── settings/ │ │ ├── base.py │ │ ├── development.py @@ -118,8 +118,8 @@ Run `just` to see all available commands, including: ├── Procfile ├── runtime.txt └── README.md -{% elif unified_structure %} -{{ project_name }}/ +# @ELSEIF unified_structure +[[ project_name ]]/ ├── apps/ │ ├── admin/ │ │ └── __init__.py @@ -158,9 +158,9 @@ Run `just` to see all available commands, including: ├── Procfile ├── runtime.txt └── README.md -{% else %} -{{ project_name }}/ -├── {{ module_name }}/ +# @ELSE +[[ project_name ]]/ +├── [[ module_name ]]/ │ ├── settings/ │ │ ├── base.py │ │ ├── development.py @@ -191,7 +191,7 @@ For example, if you have a `User` model in `models/user.py`, create: - `api/user/urls.py` - URL patterns for User endpoints See the README files in `api/` and `models/` directories for more details. -{% endif %} +# @ENDIF ``` ## API Documentation diff --git a/djinit/templates/project/requirements.j2 b/djinit/templates/project/requirements-tpl similarity index 74% rename from djinit/templates/project/requirements.j2 rename to djinit/templates/project/requirements-tpl index 381a0b7..43aee21 100644 --- a/djinit/templates/project/requirements.j2 +++ b/djinit/templates/project/requirements-tpl @@ -10,10 +10,10 @@ djangorestframework_simplejwt drf-spectacular django-cors-headers whitenoise -{% if database_type == 'mysql' %} +# @IF database_type == 'mysql' mysqlclient -{% else %} +# @ELSE psycopg[binary] -{% endif %} +# @ENDIF gunicorn -{% if use_database_url %}dj-database-url{% endif %} +dj-database-url # @IF use_database_url diff --git a/djinit/templates/project/runtime_txt-tpl b/djinit/templates/project/runtime_txt-tpl new file mode 100644 index 0000000..34ffefa --- /dev/null +++ b/djinit/templates/project/runtime_txt-tpl @@ -0,0 +1 @@ +python-[[ python_version ]] diff --git a/djinit/templates/project/runtime_txt.j2 b/djinit/templates/project/runtime_txt.j2 deleted file mode 100644 index 7cfeb51..0000000 --- a/djinit/templates/project/runtime_txt.j2 +++ /dev/null @@ -1 +0,0 @@ -python-{{ python_version }}