chore(djinit/templates): purge obsolete template components

Remove legacy template placeholders that are no longer used in the project scaffold.

- New Features:
- Enhancements: Removed unused template files
- Bug Fixes:
This commit is contained in:
sankalp committed 2026-01-31 22:23:57 +05:45
1 parent 7d76fb902c
commit e24fb36dea
46 files changed
-1870

No files matched your search

-5
View File
@@ -1,5 +0,0 @@
"""generated with djinit"""
from django.contrib import admin
# Register your models here.
@@ -1,76 +0,0 @@
# API Directory
This directory contains your API endpoints organized by model/resource.
## Structure
For each model in your `models/` directory, create a corresponding subdirectory here with the following files:
```
api/
├── __init__.py
├── urls.py # Main API URL router
└── <model_name>/ # e.g., user, product, order
├── __init__.py
├── views.py
├── serializers.py
└── urls.py
```
## Example
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
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
```
### 2. `api/user/views.py`
```python
from rest_framework import viewsets
from [[ module_name ]].models.user import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
```
### 3. `api/user/urls.py`
```python
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet
router = DefaultRouter()
router.register(r'', UserViewSet, basename='user')
urlpatterns = [
path('', include(router.urls)),
]
```
### 4. Update `api/urls.py`
```python
from django.urls import path, include
urlpatterns = [
path('user/', include('[[ module_name ]].api.user.urls')),
# Add more API endpoints here
]
```
## Best Practices
1. **One model per subdirectory**: Keep API endpoints for each model in its own subdirectory
2. **Consistent naming**: Use lowercase, plural names for API endpoints (e.g., `users/`, `products/`)
3. **Version your API**: Consider adding versioning (e.g., `api/v1/user/`)
4. **Use ViewSets**: Leverage DRF's ViewSets for standard CRUD operations
5. **Custom actions**: Add custom actions using `@action` decorator for non-CRUD operations
-12
View File
@@ -1,12 +0,0 @@
from django.apps import AppConfig
class [[ app_config_name ]]Config(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
# @IF app_module
name = '[[ app_module ]]'
# @ENDIF
# @IF not app_module
name = '[[ app_name ]]'
# @ENDIF
@@ -1,3 +0,0 @@
from django.db import models
# Create your models here.
@@ -1,119 +0,0 @@
# Models Directory
This directory contains your Django models.
## Structure
Organize your models as individual Python files:
```
models/
├── __init__.py
├── user.py
├── product.py
└── order.py
```
## Creating a Model
### 1. Create the model file (e.g., `models/user.py`)
```python
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
"""Custom user model."""
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'users'
verbose_name = 'User'
verbose_name_plural = 'Users'
def __str__(self):
return self.username
```
### 2. Import in `models/__init__.py`
```python
from .user import User
from .product import Product
from .order import Order
__all__ = ['User', 'Product', 'Order']
```
### 3. Create corresponding API endpoints
After creating a model, create the corresponding API structure in the `api/` directory:
```
api/
└── user/
├── __init__.py
├── views.py
├── serializers.py
└── urls.py
```
See the `api/README.md` for detailed instructions on creating API endpoints.
### 4. Register in admin (optional)
Create or update `admin/__init__.py`:
```python
from django.contrib import admin
from [[ module_name ]].models import User
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ['username', 'email', 'created_at']
search_fields = ['username', 'email']
list_filter = ['is_active', 'created_at']
```
## Best Practices
1. **One model per file**: Keep each model in its own file for better organization
2. **Use meaningful names**: Choose clear, descriptive names for models and fields
3. **Add Meta class**: Define `db_table`, `verbose_name`, and other metadata
4. **Implement __str__**: Always define a meaningful `__str__` method
5. **Use mixins**: Create reusable mixins for common fields (e.g., timestamps)
6. **Add docstrings**: Document your models with clear docstrings
## Common Model Patterns
### Timestamped Model Mixin
```python
class TimestampedModel(models.Model):
"""Abstract base class with timestamp fields."""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
```
### Soft Delete Mixin
```python
class SoftDeleteModel(models.Model):
"""Abstract base class with soft delete functionality."""
is_deleted = models.BooleanField(default=False)
deleted_at = models.DateTimeField(null=True, blank=True)
class Meta:
abstract = True
def delete(self, *args, **kwargs):
self.is_deleted = True
self.deleted_at = timezone.now()
self.save()
```
@@ -1,8 +0,0 @@
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
# Register your viewsets here
# router.register(r'endpoint', YourViewSet, basename='your-endpoint')
urlpatterns = router.urls
@@ -1,3 +0,0 @@
from rest_framework import serializers
# Create your serializers here.
-3
View File
@@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.
-3
View File
@@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.
-11
View File
@@ -1,11 +0,0 @@
"""generated with djinit"""
import os
import environ
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"))
application = get_asgi_application()
@@ -1,179 +0,0 @@
"""
generated with djinit
Common settings shared between development and production environment
"""
import os
from datetime import timedelta
from pathlib import Path
import environ
env = environ.Env()
environ.Env.read_env()
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# Application definition
THIRD_PARTY_APPS = [
"rest_framework",
"rest_framework_simplejwt",
"rest_framework_simplejwt.token_blacklist",
"corsheaders",
"drf_spectacular",
]
USER_DEFINED_APPS = [
# @LOOP app in app_names "[[ app ]]",
# @ENDLOOP
]
BUILT_IN_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
INSTALLED_APPS = BUILT_IN_APPS + THIRD_PARTY_APPS + USER_DEFINED_APPS
INSTALLED_APPS.insert(0, "jazzmin")
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "[[ project_name ]].urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "[[ project_name ]].wsgi.application"
# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files and media files
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_URL = "media/"
MEDIA_ROOT = BASE_DIR / "media"
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# REST Framework Settings
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES": [
"rest_framework.renderers.JSONRenderer",
],
"DEFAULT_PARSER_CLASSES": [
"rest_framework.parsers.JSONParser",
],
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 20,
}
# DRF Spectacular settings
SPECTACULAR_SETTINGS = {
"TITLE": "[[ project_name ]] API",
"DESCRIPTION": "API documentation for [[ project_name ]]",
"VERSION": "1.0.0",
"SERVE_INCLUDE_SCHEMA": False,
"COMPONENT_SPLIT_REQUEST": True,
"SCHEMA_PATH_PREFIX": "/api/",
}
# JWT Settings
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(days=1),
"REFRESH_TOKEN_LIFETIME": timedelta(days=3),
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
}
# CORS Settings
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
]
CORS_ALLOW_HEADERS = [
"accept",
"accept-encoding",
"authorization",
"content-type",
"dnt",
"origin",
"user-agent",
"x-csrftoken",
"x-requested-with",
]
CORS_PREFLIGHT_MAX_AGE = 86400 # 24 hours
# Security Settings
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = "DENY"
@@ -1,42 +0,0 @@
"""generated with djinit"""
from .base import *
SECRET_KEY = "[[ secret_key ]]"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ["*"]
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"OPTIONS": {
"transaction_mode": "IMMEDIATE",
"timeout": 5, # seconds
"init_command": """
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA mmap_size = 134217728;
PRAGMA journal_size_limit = 27103364;
PRAGMA cache_size=2000;
""",
},
}
}
# Email backend for development
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
# CORS settings for development
# Allow all origins in development (convenient but not secure)
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
# Disable HTTPS redirect in development
SECURE_SSL_REDIRECT = False
@@ -1,65 +0,0 @@
"""generated with djinit"""
from .base import *
import dj_database_url
DEBUG = False
SECRET_KEY = env('SECRET_KEY')
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=[])
# Database
# @IF use_database_url
# Using dj_database_url (recommended for production)
DATABASES = {
'default': env.db('DATABASE_URL')
}
# @ELSE
# Using individual database parameters
DATABASES = {
'default': {
# @IF database_type == 'mysql'
'ENGINE': 'django.db.backends.mysql',
'PORT': env('DB_PORT', default='3306'),
# @ELSE
'ENGINE': 'django.db.backends.postgresql',
'PORT': env('DB_PORT', default='5432'),
# @ENDIF
'NAME': env('DB_NAME'),
'USER': env('DB_USER'),
'PASSWORD': env('DB_PASSWORD'),
'HOST': env('DB_HOST'),
}
}
# @ENDIF
# CORS settings for production
# Filter out empty strings from FRONTEND_URL
CORS_ALLOWED_ORIGINS = env.list('FRONTEND_URL', default=[])
CORS_ALLOW_CREDENTIALS = True
# Additional CORS security for production
CORS_ALLOW_PRIVATE_NETWORK = False
# Email settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env('EMAIL_HOST')
EMAIL_PORT = env.int('EMAIL_PORT', default=587)
EMAIL_USE_TLS = env.bool('EMAIL_USE_TLS', default=True)
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
DEFAULT_FROM_EMAIL = env('EMAIL_HOST_USER')
SERVER_EMAIL = env('EMAIL_HOST_USER')
# Security settings for production
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Session settings
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# Static files
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
-103
View File
@@ -1,103 +0,0 @@
# @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
-12
View File
@@ -1,12 +0,0 @@
"""generated with djinit"""
import os
import environ
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"))
application = get_wsgi_application()
@@ -1,18 +0,0 @@
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
@@ -1,11 +0,0 @@
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"]
@@ -1,36 +0,0 @@
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()
@@ -1,55 +0,0 @@
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)
@@ -1,62 +0,0 @@
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)
@@ -1,9 +0,0 @@
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
"""Custom user model extending Django's AbstractUser."""
# Add custom fields here if needed
pass
@@ -1,9 +0,0 @@
from rest_framework import serializers
from apps.users.models.user import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["id", "username", "email", "first_name", "last_name"]
@@ -1,10 +0,0 @@
from typing import Optional
from apps.users.models.user import User
def get_user_by_id(user_id: int) -> Optional[User]:
try:
return User.objects.get(id=user_id)
except User.DoesNotExist:
return None
@@ -1,12 +0,0 @@
import pytest
from django.urls import reverse
from rest_framework.test import APIClient
@pytest.mark.django_db
def test_users_list_empty():
client = APIClient()
url = reverse("v1:users-list")
response = client.get(url)
assert response.status_code == 200
assert response.json() == []
@@ -1,13 +0,0 @@
from rest_framework import status, viewsets
from rest_framework.response import Response
from apps.users.models.user import User
from apps.users.serializers.user_serializer import UserSerializer
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
@@ -1,5 +0,0 @@
class ApplicationError(Exception):
"""Base application exception."""
def __init__(self, message: str):
super().__init__(message)
@@ -1,14 +0,0 @@
import logging
logger = logging.getLogger(__name__)
class RequestLoggerMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
logger.info("%s %s", request.method, request.path)
response = self.get_response(request)
return response
@@ -1,9 +0,0 @@
from django.db import models
class TimestampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
@@ -1,17 +0,0 @@
# @IF include_header
"""generated with djinit"""
# @ENDIF
from rest_framework.response import Response
def success(data=None, status_code=200):
# @IF include_docstrings """Return a successful response."""
# @ENDIF
return Response({"success": True, "data": data}, status=status_code)
def error(message, status_code=400):
# @IF include_docstrings """Return an error response."""
# @ENDIF
return Response({"success": False, "message": message}, status=status_code)
@@ -1,8 +0,0 @@
"""generated with djinit"""
from django.apps import AppConfig
class CoreConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.core"
@@ -1,4 +0,0 @@
from .base import AbstractBaseModel
from .mixins import TimestampedModel
__all__ = ["AbstractBaseModel", "TimestampedModel"]
@@ -1,13 +0,0 @@
"""generated with djinit"""
from django.db import models
class AbstractBaseModel(models.Model):
"""Abstract base model with common fields."""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
@@ -1,13 +0,0 @@
"""generated with djinit"""
from django.db import models
class TimestampedModel(models.Model):
"""Mixin for models that need timestamp fields."""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
@@ -1,3 +0,0 @@
from .responses import success, error
__all__ = ["success", "error"]
@@ -1,109 +0,0 @@
name: Django CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12", "3.13"]
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test_db
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- name: Set up Python {{ '{{ matrix.python-version }}' }}
uses: actions/setup-python@v5
with:
python-version: {{ '{{ matrix.python-version }}' }}
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
- name: Install dependencies
run: uv sync
- name: Run linting
run: uv run ruff check .
- name: Format check
run: uv run ruff format --check .
- name: Set up PostgreSQL
env:
DB_NAME: test_db
DB_USER: postgres
DB_PASSWORD: postgres
DB_HOST: localhost
DB_PORT: 5432
run: |
echo "PostgreSQL is ready"
- name: Run Django tests
env:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
DB_NAME: test_db
DB_USER: postgres
DB_PASSWORD: postgres
DB_HOST: localhost
DB_PORT: 5432
run: |
uv run python manage.py check
uv run python manage.py test
- name: Check migrations
env:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
DB_NAME: test_db
DB_USER: postgres
DB_PASSWORD: postgres
DB_HOST: localhost
DB_PORT: 5432
run: |
uv run python manage.py makemigrations --check --dry-run
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
- name: Install dependencies
run: uv sync
- name: Run security check
run: uv run python manage.py check --deploy
-133
View File
@@ -1,133 +0,0 @@
# GitLab CI/CD configuration for [[ project_name ]]
stages:
- test
- lint
- security
variables:
POSTGRES_DB: test_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/test_db"
# Use Docker-in-Docker
services:
- postgres:15
before_script:
- python --version
- pip install uv
- uv sync
# Lint stage
lint:
stage: lint
image: python:3.13
script:
- uv run ruff check .
- uv run ruff format --check .
only:
- branches
- merge_requests
# Test stage
test:
stage: test
image: python:3.13
variables:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
script:
- uv run python manage.py check
- uv run python manage.py migrate
- uv run python manage.py test
only:
- branches
- merge_requests
# Multiple Python versions
test:python310:
stage: test
image: python:3.10
variables:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
script:
- pip install uv
- uv sync
- uv run python manage.py check
- uv run python manage.py migrate
- uv run python manage.py test
only:
- branches
- merge_requests
test:python311:
stage: test
image: python:3.11
variables:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
script:
- pip install uv
- uv sync
- uv run python manage.py check
- uv run python manage.py migrate
- uv run python manage.py test
only:
- branches
- merge_requests
test:python312:
stage: test
image: python:3.12
variables:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
script:
- pip install uv
- uv sync
- uv run python manage.py check
- uv run python manage.py migrate
- uv run python manage.py test
only:
- branches
- merge_requests
test:python313:
stage: test
image: python:3.13
variables:
DJANGO_SETTINGS_MODULE: [[ module_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
ALLOWED_HOSTS: localhost
script:
- pip install uv
- uv sync
- uv run python manage.py check
- uv run python manage.py migrate
- uv run python manage.py test
only:
- branches
- merge_requests
# Security check
security:
stage: security
image: python:3.13
variables:
DJANGO_SETTINGS_MODULE: [[ project_name ]].settings.development
SECRET_KEY: test-secret-key-for-ci
script:
- pip install uv
- uv sync
- uv run python manage.py check --deploy
- uv run python manage.py validate_templates
only:
- main
- develop
-32
View File
@@ -1,32 +0,0 @@
# Django settings
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
# 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
# Database (individual parameters)
DB_NAME=
DB_USER=
DB_PASSWORD=
DB_HOST=
DB_PORT=
# @ENDIF
# Frontend URL
FRONTEND_URL=http://frontend.your-domain.com
# Email settings
EMAIL_HOST=
EMAIL_PORT=
EMAIL_USE_TLS=
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
DEFAULT_FROM_EMAIL=
SERVER_EMAIL=
-93
View File
@@ -1,93 +0,0 @@
#--------------------------------------------------#
# The following was generated by djinit: #
#--------------------------------------------------#
# Python
*.py[cod]
*$py.class
*.so
__pycache__/
*.egg-info/
dist/
build/
.eggs/
*.egg
# Django
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
*.sqlite3
# Environment
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# IDEs
.vscode/
.idea/
*.swp
*.swo
*~
.project
.pydevproject
.settings/
.ropeproject/
# OS
.DS_Store
*.DS_Store
Thumbs.db
desktop.ini
# Django specific
media/
staticfiles/
staticfiles/
static_root/
/static/
# Testing
.coverage
htmlcov/
.pytest_cache/
.tox/
coverage.xml
*.cover
.hypothesis/
.cache
# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Node modules (if using frontend tools)
node_modules/
# Secret keys
secret.txt
secrets.json
# Jupyter Notebook
.ipynb_checkpoints
# Backup files
*.bak
*.tmp
*~
# Database
*.db
*.sql
# Cloud
.cloud
Whitespace-only changes.
-219
View File
@@ -1,219 +0,0 @@
# Justfile for [[ project_name ]]
# Task runner for Django development
# Install just: https://github.com/casey/just
# Default task: show available commands
default:
@just --list
# Run development server
dev:
uv run python manage.py runserver
# Run development server with custom host and port
dev-server HOST="0.0.0.0" PORT="8000":
uv run python manage.py runserver {{ '{{' }}HOST{{ '}}' }}:{{ '{{' }}PORT{{ '}}' }}
# Create migrations for all apps
makemigrations:
uv run python manage.py makemigrations
# Create migrations for specific app
makemigrations-app APP:
uv run python manage.py makemigrations {{ '{{' }}APP{{ '}}' }}
# Run all migrations
migrate:
uv run python manage.py migrate
# Reset database (delete all migrations)
reset-db:
uv run python manage.py flush --noinput
uv run python manage.py migrate
# Create superuser
createsuperuser:
uv run python manage.py createsuperuser
# Collect static files
collectstatic:
uv run python manage.py collectstatic --noinput
# Run Django shell
shell:
uv run python manage.py shell
# Run Django shell plus (IPython)
shell-plus:
uv run python manage.py shell_plus
# Run tests
test:
uv run python manage.py test
# Run tests with coverage
test-coverage:
uv run pytest --cov=. --cov-report=html --cov-report=term
# Lint code with ruff
lint:
uv run ruff check .
# Format code with ruff
format:
uv run ruff format .
# Lint and format code
style:
uv run ruff check .
uv run ruff format .
# Check security issues
check:
uv run python manage.py check
# Check security issues (production settings)
check-deploy:
uv run python manage.py check --deploy
# Show all database migrations status
showmigrations:
uv run python manage.py showmigrations
# Sync dependencies (uv equivalent of pip freeze)
requirements:
uv pip compile
# Run all linting and checks
ci:
uv run ruff check .
uv run ruff format --check .
uv run python manage.py check
# Start interactive shell
shell-ipython:
uv run python manage.py shell_plus
# Clear all cache
clear-cache:
uv run python manage.py clear_cache
# Show Django version
version:
uv run python manage.py version
# Run database shell
dbshell:
uv run python manage.py dbshell
# Start production server with gunicorn
server:
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{{ '}}' }}
# 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
# Clean Python cache files
clean:
find . -type d -name "__pycache__" -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
find . -type f -name "*.pyo" -delete
find . -type f -name ".coverage" -delete
find . -type d -name "*.egg-info" -exec rm -rf {} +
rm -rf htmlcov/
rm -rf .pytest_cache/
# Pin dependencies in pyproject.toml using versions from uv.lock, keeping >= and extras
pin-deps:
#!/usr/bin/env -S uv run python
import tomllib, re
from pathlib import Path
lock = Path("uv.lock")
if not lock.exists():
print("uv.lock not found — run `uv sync` first")
raise SystemExit(0)
data = tomllib.loads(lock.read_text())
packages = {p["name"].lower(): p["version"] for p in data.get("package", [])}
py = Path("pyproject.toml")
lines = py.read_text().splitlines()
pattern = re.compile(r'^(\s*)"([^"]+)"(,?)')
out = []
for line in lines:
m = pattern.match(line)
if not m:
out.append(line)
continue
indent, dep, comma = m.groups()
base = dep
extras = ""
operator = ">="
version = None
# extras: django[postgres]
if "[" in base and "]" in base:
before, after = base.split("[", 1)
extras = "[" + after.split("]")[0] + "]"
base = before
# detect >= or ==
if ">=" in dep:
operator = ">="
base, version = dep.split(">=")
base = base.strip()
elif "==" in dep:
operator = "=="
base, version = dep.split("==")
base = base.strip()
else:
base = dep
base_lower = base.lower()
new_version = packages.get(base_lower)
if new_version:
new_dep = f'{base}{extras}{operator}{new_version}'
line = f'{indent}"{new_dep}"{comma}'
out.append(line)
py.write_text("\n".join(out) + "\n")
print("Pinned dependencies (>= preserved, extras preserved).")
# Setup project for development (using uv)
setup:
uv sync
just pin-deps
uv run python manage.py migrate
uv run python manage.py createsuperuser
# Complete setup including static files
setup-complete:
uv sync
uv run python manage.py migrate
uv run python manage.py collectstatic --noinput
uv run python manage.py createsuperuser
# Install a new package
install PACKAGE:
uv add {{ '{{' }}PACKAGE{{ '}}' }}
# Install a dev package
install-dev PACKAGE:
uv add --dev {{ '{{' }}PACKAGE{{ '}}' }}
# Remove a package
remove PACKAGE:
uv remove {{ '{{' }}PACKAGE{{ '}}' }}
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env python
"""generated with djinit"""
"""Django's command-line utility for administrative tasks."""
import os
import sys
import environ
def main():
"""Run administrative tasks."""
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
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
env = environ.Env()
# Read .env file, if it exists
environ.Env.read_env()
main()
-20
View File
@@ -1,20 +0,0 @@
# 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
# 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
# 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
# Development server (for local testing with Foreman/Overmind)
# web: python manage.py runserver 0.0.0.0:$PORT
@@ -1,46 +0,0 @@
[project]
name = "[[ package_name ]]"
version = "0.1.0"
description = ""
readme = "README.md"
requires-python = ">=3.13"
license = { text = "MIT" }
dependencies = [
"django",
"django-environ",
"django-jazzmin",
"djangorestframework",
"djangorestframework-simplejwt",
"drf-spectacular",
"django-cors-headers",
"whitenoise",
# @IF database_type == 'mysql'
"mysqlclient",
# @ENDIF
# @IF database_type == 'postgresql'
"psycopg2-binary",
# @ENDIF
"gunicorn",
]
[tool.ruff]
line-length = 88
target-version = "py38"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]
ignore = [
"E501", # line too long, handled by formatter
"B008", # do not perform function calls in argument defaults
]
[tool.ruff.lint.isort]
known-first-party = ["[[ project_name ]]"]
-201
View File
@@ -1,201 +0,0 @@
# [[ project_name ]]
A Django project folder structure is generated with [djinitx/djinit/dj](https://github.com/S4NKALP/djinit).
## Features
- Modern project structure with environment-specific settings
- Pre-configured REST API with JWT authentication
- Essential dependencies and utilities
- Production-ready configuration
## Setup
### Using Just (Recommended)
1. Set environment variables in `.env` file
2. Run setup (installs dependencies, runs migrations, creates superuser):
```bash
just setup
```
3. Start development server:
```bash
just dev
```
### Traditional Method
1. Install dependencies:
```bash
pip install -r requirements.txt
```
2. Set environment variables in `.env` file
3. Run migrations:
```bash
python manage.py migrate
```
4. Create superuser:
```bash
python manage.py createsuperuser
```
5. Start development server:
```bash
python manage.py runserver
```
## Available Commands
Run `just` to see all available commands, including:
- `just dev` - Run development server
- `just migrate` - Run migrations
- `just makemigrations` - Create migrations
- `just createsuperuser` - Create superuser
- `just test` - Run tests
- `just lint` - Lint code
- `just format` - Format code
- `just shell` - Django shell
- `just clean` - Clean cache files
- `just install <package>` - Install package
- `just remove <package>` - Remove package
- `just server` - Run production server
- `just ci` - Run all linting and checks
- `just test-coverage` - Run tests with coverage
## Project Structure
```
# @IF predefined_structure
[[ project_name ]]/
├── [[ module_name ]]/
│ ├── settings/
│ │ ├── base.py
│ │ ├── development.py
│ │ └── production.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── apps/
│ ├── users/
│ │ ├── apps.py
│ │ ├── models/
│ │ │ └── user.py
│ │ ├── serializers/
│ │ │ └── user_serializer.py
│ │ ├── services/
│ │ │ └── user_service.py
│ │ ├── views/
│ │ │ └── user_view.py
│ │ ├── urls.py
│ │ └── tests/
│ │ └── test_user_api.py
│ └── core/
│ ├── utils/
│ │ └── responses.py
│ ├── mixins/
│ │ └── timestamped_model.py
│ ├── exceptions.py
│ └── middleware/
│ └── request_logger.py
├── api/
│ ├── __init__.py
│ ├── urls.py
│ └── v1/
│ ├── __init__.py
│ └── urls.py
├── manage.py
├── requirements.txt
├── pyproject.toml
├── uv.lock
├── .env.sample
├── justfile
├── Procfile
├── runtime.txt
└── README.md
# @ELSEIF unified_structure
[[ project_name ]]/
├── apps/
│ ├── admin/
│ │ └── __init__.py
│ ├── api/
│ │ ├── __init__.py
│ │ ├── urls.py
│ │ └── v1/
│ │ ├── __init__.py
│ │ └── urls.py
│ ├── models/
│ │ └── __init__.py
│ ├── serializers/
│ │ └── __init__.py
│ ├── tests/
│ │ └── __init__.py
│ ├── urls/
│ │ └── __init__.py
│ └── views/
│ └── __init__.py
├── core/
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings/
│ │ ├── base.py
│ │ ├── development.py
│ │ ├── __init__.py
│ │ └── production.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── requirements.txt
├── pyproject.toml
├── uv.lock
├── .env.sample
├── justfile
├── Procfile
├── runtime.txt
└── README.md
# @ELSE
[[ project_name ]]/
├── [[ module_name ]]/
│ ├── settings/
│ │ ├── base.py
│ │ ├── development.py
│ │ └── production.py
│ ├── admin/
│ ├── api/ # API endpoints organized by model
│ │ ├── user/ # Example: if you have a User model
│ │ │ ├── views.py
│ │ │ ├── serializers.py
│ │ │ └── urls.py
│ │ └── urls.py
│ ├── models/ # Django models
│ ├── tests/
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── manage.py
├── requirements.txt
├── pyproject.toml
├── uv.lock
├── .env.sample
└── README.md
**Note:** For the single folder layout, organize your API endpoints by model name under the `api/` directory.
For example, if you have a `User` model in `models/user.py`, create:
- `api/user/views.py` - API views for User
- `api/user/serializers.py` - Serializers for User
- `api/user/urls.py` - URL patterns for User endpoints
See the README files in `api/` and `models/` directories for more details.
# @ENDIF
```
## API Documentation
When running in development mode, API documentation is available at:
- Swagger UI: http://localhost:8000/docs/
- Schema: http://localhost:8000/schema/
-19
View File
@@ -1,19 +0,0 @@
#--------------------------------------------------#
# The following was generated by djinit: #
#--------------------------------------------------#
Django
django-environ
django-jazzmin
djangorestframework
djangorestframework_simplejwt
drf-spectacular
django-cors-headers
whitenoise
# @IF database_type == 'mysql'
mysqlclient
# @ELSE
psycopg[binary]
# @ENDIF
gunicorn
dj-database-url # @IF use_database_url
-1
View File
@@ -1 +0,0 @@
python-[[ python_version ]]