django-cfg 1.4.93__py3-none-any.whl → 1.4.94__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-cfg might be problematic. Click here for more details.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/frontend/views.py +32 -36
- django_cfg/modules/nextjs_admin/views.py +10 -4
- django_cfg/pyproject.toml +1 -1
- django_cfg/static/frontend/nextjs_admin.zip +0 -0
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.94.dist-info}/METADATA +1 -1
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.94.dist-info}/RECORD +10 -10
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.94.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.94.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.94.dist-info}/licenses/LICENSE +0 -0
django_cfg/__init__.py
CHANGED
|
@@ -28,21 +28,24 @@ logger = logging.getLogger(__name__)
|
|
|
28
28
|
|
|
29
29
|
class ZipExtractionMixin:
|
|
30
30
|
"""
|
|
31
|
-
Mixin for automatic ZIP extraction with
|
|
31
|
+
Mixin for automatic ZIP extraction with age-based refresh.
|
|
32
32
|
|
|
33
33
|
Provides intelligent ZIP archive handling:
|
|
34
34
|
- Auto-extraction when directory doesn't exist
|
|
35
|
-
- Auto-reextraction when
|
|
36
|
-
-
|
|
35
|
+
- Auto-reextraction when extracted directory is older than 10 minutes
|
|
36
|
+
- Simple age-based logic (no ZIP timestamp comparison needed)
|
|
37
37
|
|
|
38
38
|
Usage:
|
|
39
39
|
class MyView(ZipExtractionMixin, View):
|
|
40
40
|
app_name = 'myapp' # Will look for myapp.zip
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
+
# Maximum age of extracted directory before re-extraction (in seconds)
|
|
44
|
+
MAX_DIRECTORY_AGE = 600 # 10 minutes = 600 seconds
|
|
45
|
+
|
|
43
46
|
def extract_zip_if_needed(self, base_dir: Path, zip_path: Path, app_name: str) -> bool:
|
|
44
47
|
"""
|
|
45
|
-
Extract ZIP archive if needed based on
|
|
48
|
+
Extract ZIP archive if needed based on directory age.
|
|
46
49
|
|
|
47
50
|
Args:
|
|
48
51
|
base_dir: Target directory for extraction
|
|
@@ -57,33 +60,25 @@ class ZipExtractionMixin:
|
|
|
57
60
|
# Priority 1: If directory doesn't exist at all - always extract
|
|
58
61
|
if not base_dir.exists():
|
|
59
62
|
should_extract = True
|
|
60
|
-
logger.info(f"[{app_name}] Directory
|
|
61
|
-
|
|
62
|
-
# Priority 2: Directory exists - check if
|
|
63
|
-
|
|
64
|
-
# Get
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# If
|
|
69
|
-
if
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
logger.
|
|
76
|
-
|
|
77
|
-
shutil.rmtree(base_dir)
|
|
78
|
-
should_extract = True
|
|
79
|
-
except Exception as e:
|
|
80
|
-
logger.error(f"[{app_name}] Failed to remove old directory: {e}")
|
|
81
|
-
return False
|
|
82
|
-
else:
|
|
83
|
-
logger.debug(f"[{app_name}] ZIP is fresh but directory is up-to-date")
|
|
63
|
+
logger.info(f"[{app_name}] Directory doesn't exist, will extract")
|
|
64
|
+
|
|
65
|
+
# Priority 2: Directory exists - check if it's too old
|
|
66
|
+
else:
|
|
67
|
+
# Get directory modification time
|
|
68
|
+
dir_mtime = datetime.fromtimestamp(base_dir.stat().st_mtime)
|
|
69
|
+
directory_age = (datetime.now() - dir_mtime).total_seconds()
|
|
70
|
+
|
|
71
|
+
# If directory is older than MAX_DIRECTORY_AGE - re-extract
|
|
72
|
+
if directory_age > self.MAX_DIRECTORY_AGE:
|
|
73
|
+
logger.info(f"[{app_name}] Directory is old ({directory_age:.0f}s > {self.MAX_DIRECTORY_AGE}s), re-extracting")
|
|
74
|
+
try:
|
|
75
|
+
shutil.rmtree(base_dir)
|
|
76
|
+
should_extract = True
|
|
77
|
+
except Exception as e:
|
|
78
|
+
logger.error(f"[{app_name}] Failed to remove old directory: {e}")
|
|
79
|
+
return False
|
|
84
80
|
else:
|
|
85
|
-
|
|
86
|
-
logger.debug(f"[{app_name}] ZIP is old ({time_since_modification:.0f}s), using existing")
|
|
81
|
+
logger.debug(f"[{app_name}] Directory is fresh ({directory_age:.0f}s), using existing")
|
|
87
82
|
|
|
88
83
|
# Extract ZIP if needed
|
|
89
84
|
if should_extract:
|
|
@@ -102,7 +97,7 @@ class ZipExtractionMixin:
|
|
|
102
97
|
logger.error(f"[{app_name}] ZIP not found: {zip_path}")
|
|
103
98
|
return False
|
|
104
99
|
|
|
105
|
-
# Directory exists and is
|
|
100
|
+
# Directory exists and is fresh
|
|
106
101
|
return True
|
|
107
102
|
|
|
108
103
|
|
|
@@ -113,17 +108,18 @@ class NextJSStaticView(ZipExtractionMixin, View):
|
|
|
113
108
|
|
|
114
109
|
Features:
|
|
115
110
|
- Serves Next.js static export files like a static file server
|
|
116
|
-
- Smart ZIP extraction: auto-
|
|
111
|
+
- Smart ZIP extraction: auto-refreshes when directory older than 10 minutes
|
|
117
112
|
- Automatically injects JWT tokens for authenticated users
|
|
118
113
|
- Tokens injected into HTML responses only
|
|
119
114
|
- Handles Next.js client-side routing (.html fallback)
|
|
120
115
|
- Automatically serves index.html for directory paths
|
|
121
116
|
- X-Frame-Options exempt to allow embedding in iframes
|
|
122
117
|
|
|
123
|
-
ZIP
|
|
124
|
-
- If
|
|
125
|
-
- If
|
|
126
|
-
-
|
|
118
|
+
ZIP Extraction Logic:
|
|
119
|
+
- If directory doesn't exist: extract from ZIP
|
|
120
|
+
- If directory older than 10 minutes: remove and re-extract
|
|
121
|
+
- If directory fresh (< 10 min): use existing files
|
|
122
|
+
- This enables auto-refresh during development while caching in production
|
|
127
123
|
|
|
128
124
|
Path resolution examples:
|
|
129
125
|
- /cfg/admin/ → /cfg/admin/index.html
|
|
@@ -4,8 +4,8 @@ Views for Next.js admin integration.
|
|
|
4
4
|
Serves Next.js static files with SPA routing support and JWT injection.
|
|
5
5
|
|
|
6
6
|
Features:
|
|
7
|
-
- Automatic extraction of ZIP archives with
|
|
8
|
-
- Auto-reextraction when
|
|
7
|
+
- Automatic extraction of ZIP archives with age-based refresh
|
|
8
|
+
- Auto-reextraction when directory is older than 10 minutes
|
|
9
9
|
- SPA routing with fallback strategies
|
|
10
10
|
- JWT token injection for authenticated users
|
|
11
11
|
"""
|
|
@@ -31,13 +31,19 @@ class NextJsAdminView(ZipExtractionMixin, LoginRequiredMixin, View):
|
|
|
31
31
|
|
|
32
32
|
Features:
|
|
33
33
|
- Serves Next.js static build files
|
|
34
|
+
- Smart ZIP extraction: auto-refreshes when directory older than 10 minutes
|
|
34
35
|
- Automatic JWT token injection for authenticated users
|
|
35
36
|
- SPA routing support (path/to/route → path/to/route/index.html)
|
|
36
37
|
- Development mode support (proxies to dev server conceptually)
|
|
37
38
|
|
|
39
|
+
ZIP Extraction Logic:
|
|
40
|
+
- If directory doesn't exist: extract from ZIP
|
|
41
|
+
- If directory older than 10 minutes: remove and re-extract
|
|
42
|
+
- If directory fresh (< 10 min): use existing files
|
|
43
|
+
|
|
38
44
|
URL Examples:
|
|
39
|
-
/cfg/admin/ →
|
|
40
|
-
/cfg/admin/
|
|
45
|
+
/cfg/admin/ → admin/index.html
|
|
46
|
+
/cfg/admin/crypto → admin/crypto/index.html
|
|
41
47
|
/cfg/admin/_next/static/... → _next/static/...
|
|
42
48
|
"""
|
|
43
49
|
|
django_cfg/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "django-cfg"
|
|
7
|
-
version = "1.4.
|
|
7
|
+
version = "1.4.94"
|
|
8
8
|
description = "Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "nextjs-admin", "react-admin", "websocket", "centrifugo", "real-time", "typescript-generation", "ai-agents", "enterprise-django", "django-settings", "type-safe-config", "modern-django",]
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-cfg
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.94
|
|
4
4
|
Summary: Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features.
|
|
5
5
|
Project-URL: Homepage, https://djangocfg.com
|
|
6
6
|
Project-URL: Documentation, https://djangocfg.com
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
django_cfg/__init__.py,sha256
|
|
2
|
+
django_cfg/__init__.py,sha256=-eM13Z1Uie8EJUy2384SNHfso1SqzwpkDsmrQgWQN3w,1620
|
|
3
3
|
django_cfg/apps.py,sha256=72m3uuvyqGiLx6gOfE-BD3P61jddCCERuBOYpxTX518,1605
|
|
4
4
|
django_cfg/config.py,sha256=y4Z3rnYsHBE0TehpwAIPaxr---mkvyKrZGGsNwYso74,1398
|
|
5
5
|
django_cfg/apps/__init__.py,sha256=JtDmEYt1OcleWM2ZaeX0LKDnRQzPOavfaXBWG4ECB5Q,26
|
|
@@ -228,7 +228,7 @@ django_cfg/apps/frontend/apps.py,sha256=9eEK0Tq2nOsol7xSK5aobdwTDJTJrWx6Iy1I1DQb
|
|
|
228
228
|
django_cfg/apps/frontend/setup.py,sha256=TxKQwQw4xTF6VSyhrQBzbUsdsVQR9JHdjc36LZKeQh4,2444
|
|
229
229
|
django_cfg/apps/frontend/test_routing.py,sha256=fshJOR9ln7m3gXY9EI1_ix_6E5xua6DR264b16RIF-w,4832
|
|
230
230
|
django_cfg/apps/frontend/urls.py,sha256=Vz22_2i2w1J0KQYDCxHnTF5rUf32kUUSBDJZrP07XgY,284
|
|
231
|
-
django_cfg/apps/frontend/views.py,sha256=
|
|
231
|
+
django_cfg/apps/frontend/views.py,sha256=JkObFoAJATT2gy6TnyFi0LrjQm7HGWaRy3vr2zdTs4E,13586
|
|
232
232
|
django_cfg/apps/frontend/templates/frontend/404.html,sha256=LCFig_dcgDDmYKhgOLu8R2KDs_aQS6Es6rAxLTAEXWs,2175
|
|
233
233
|
django_cfg/apps/knowbase/README.md,sha256=HXt_J6WCN-LsMhA7p9mdvih07_vp_r_hkPdmqHhNEeo,3965
|
|
234
234
|
django_cfg/apps/knowbase/__init__.py,sha256=cfGnxDQwjajPhUoleKkgvdabJcB0LdXEglnsBojKkPo,1045
|
|
@@ -1021,7 +1021,7 @@ django_cfg/modules/django_unfold/models/navigation.py,sha256=PPEeqA2HBaA1-VjADiX
|
|
|
1021
1021
|
django_cfg/modules/nextjs_admin/__init__.py,sha256=lfrZYyNRExH3Z5De8G4hQBIZoFlW5Ejze3couNrztbY,312
|
|
1022
1022
|
django_cfg/modules/nextjs_admin/apps.py,sha256=HxVUMmWTKdYpwJ00iIfWVFsBzsawsOVhEPZqjk_izjI,347
|
|
1023
1023
|
django_cfg/modules/nextjs_admin/urls.py,sha256=7n0yStm0WNchw14Rtu_mgsIA3WKQsYP9WZt3-YOUWjU,603
|
|
1024
|
-
django_cfg/modules/nextjs_admin/views.py,sha256=
|
|
1024
|
+
django_cfg/modules/nextjs_admin/views.py,sha256=lOcK-XLucWn-W4LORgk0XBEJkolYvSvsnp4Pq77oBBY,9657
|
|
1025
1025
|
django_cfg/modules/nextjs_admin/models/__init__.py,sha256=WGw9KXcYd1O9AoA_bpMoz2gLZUlRzjGmUBjjbObcUi0,100
|
|
1026
1026
|
django_cfg/modules/nextjs_admin/models/config.py,sha256=0ADqLuiywSCQfx_z9dkwjFCca3lr3F2uQffIjTr_QXw,5864
|
|
1027
1027
|
django_cfg/modules/nextjs_admin/templatetags/__init__.py,sha256=ChVBnJggCIY8rMhfyJFoA8k0qKo-8FtJknrk54Vx4wM,51
|
|
@@ -1051,7 +1051,7 @@ django_cfg/static/admin/js/alpine/dashboard-tabs.js,sha256=ob8Q_I9lFLDv_hFERXgTy
|
|
|
1051
1051
|
django_cfg/static/admin/js/alpine/system-metrics.js,sha256=m-Fg55K_vpHXToD46PXL9twl4OBF_V9MONvbSWbQqDw,440
|
|
1052
1052
|
django_cfg/static/admin/js/alpine/toggle-section.js,sha256=T141NFmy0fRJyGGuuaCJRjJXwPam-xxtQNW1hi8BJbc,672
|
|
1053
1053
|
django_cfg/static/frontend/admin.zip,sha256=n2G8ajruLqojcjqvw2pMEPjgpSTTwcmJxkeIQxJVw9U,7626768
|
|
1054
|
-
django_cfg/static/frontend/nextjs_admin.zip,sha256=
|
|
1054
|
+
django_cfg/static/frontend/nextjs_admin.zip,sha256=BsnMjrr9vx1Lh1zadBEBFGeP-Cn_eLjhWfkWk1m0fEw,7548272
|
|
1055
1055
|
django_cfg/static/js/api-loader.mjs,sha256=boGqqRGnFR-Mzo_RQOjhAzNvsb7QxZddSwMKROzkk9Q,5163
|
|
1056
1056
|
django_cfg/static/js/api/base.mjs,sha256=KUxZHHdELAV8mNnACpwJRvaQhdJxp-n5LFEQ4oUZxBo,4707
|
|
1057
1057
|
django_cfg/static/js/api/index.mjs,sha256=_-Q04jjHcgwi4CGfiaLyiOR6NW7Yu1HBhJWp2J1cjpc,2538
|
|
@@ -1085,9 +1085,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
|
|
|
1085
1085
|
django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
|
|
1086
1086
|
django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
|
|
1087
1087
|
django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
|
1088
|
-
django_cfg/pyproject.toml,sha256=
|
|
1089
|
-
django_cfg-1.4.
|
|
1090
|
-
django_cfg-1.4.
|
|
1091
|
-
django_cfg-1.4.
|
|
1092
|
-
django_cfg-1.4.
|
|
1093
|
-
django_cfg-1.4.
|
|
1088
|
+
django_cfg/pyproject.toml,sha256=J8hwDLhnybgAGUsvUNdXFimKoEuj7Lc9SH1n5f_Q0gY,8572
|
|
1089
|
+
django_cfg-1.4.94.dist-info/METADATA,sha256=Xhg1mauCgGfgGYkYBGmGWH19KcqlRxLi4z-kGAGFvVs,23733
|
|
1090
|
+
django_cfg-1.4.94.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
1091
|
+
django_cfg-1.4.94.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
|
|
1092
|
+
django_cfg-1.4.94.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
|
1093
|
+
django_cfg-1.4.94.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|