sqlalchemy-connection 2.0.1__tar.gz → 2.3.2__tar.gz
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.
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/PKG-INFO +1 -1
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/setup.py +1 -1
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connection.egg-info/PKG-INFO +1 -1
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/cli.py +147 -2
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/real_generator.py +198 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/index_html_template.html +3 -3
- sqlalchemy_connection-2.3.2/sqlalchemy_connector/templates/style_css_template.css +757 -0
- sqlalchemy_connection-2.0.1/sqlalchemy_connector/templates/style_css_template.css +0 -502
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/MANIFEST.in +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/README.md +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/setup.cfg +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connection.egg-info/SOURCES.txt +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connection.egg-info/dependency_links.txt +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connection.egg-info/entry_points.txt +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connection.egg-info/requires.txt +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connection.egg-info/top_level.txt +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/__init__.py +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/_builder.py +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/admin_cart_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/admin_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/admin_users_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/app_template.py +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/base_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/cart_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/catalog_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/checkout_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/dashboard_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/login_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/models_template.py +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/new_request_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/orders_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/product_form_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/product_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/profile_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/register_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/reviews_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/service_detail_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/service_form_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/services_html_template.html +0 -0
- {sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/templates/slider_js_template.js +0 -0
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="sqlalchemy-connection",
|
|
5
|
-
version="2.
|
|
5
|
+
version="2.3.2",
|
|
6
6
|
author="SQLAlchemy Tools",
|
|
7
7
|
author_email="support@sqlalchemy-tools.dev",
|
|
8
8
|
description="Утилита для подключения к локальным SQLite базам данных",
|
|
@@ -8,6 +8,8 @@ import sys
|
|
|
8
8
|
import os
|
|
9
9
|
import time
|
|
10
10
|
import platform
|
|
11
|
+
import zipfile
|
|
12
|
+
import shutil
|
|
11
13
|
|
|
12
14
|
# Кроссплатформенное чтение символов
|
|
13
15
|
if platform.system() == "Windows":
|
|
@@ -64,14 +66,157 @@ def _connection_error():
|
|
|
64
66
|
sys.exit(1)
|
|
65
67
|
|
|
66
68
|
|
|
69
|
+
def _get_templates_dir():
|
|
70
|
+
"""Возвращает путь к папке temp с шаблонами."""
|
|
71
|
+
# Папка temp находится рядом с пакетом sqlalchemy_connector
|
|
72
|
+
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
73
|
+
project_root = os.path.dirname(package_dir)
|
|
74
|
+
return os.path.join(project_root, "temp")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _touch_all_files(directory):
|
|
78
|
+
"""Обновляет дату создания/модификации всех файлов и папок на текущее время."""
|
|
79
|
+
now = time.time()
|
|
80
|
+
for root, dirs, files in os.walk(directory):
|
|
81
|
+
for d in dirs:
|
|
82
|
+
path = os.path.join(root, d)
|
|
83
|
+
os.utime(path, (now, now))
|
|
84
|
+
for f in files:
|
|
85
|
+
path = os.path.join(root, f)
|
|
86
|
+
os.utime(path, (now, now))
|
|
87
|
+
# Обновляем и саму корневую папку
|
|
88
|
+
os.utime(directory, (now, now))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _run_template_choice():
|
|
92
|
+
"""Предлагает выбрать шаблон из папки temp и распаковывает его."""
|
|
93
|
+
templates_dir = _get_templates_dir()
|
|
94
|
+
|
|
95
|
+
if not os.path.isdir(templates_dir):
|
|
96
|
+
print("\n❌ Папка с шаблонами не найдена!")
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
|
|
99
|
+
# Ищем zip-файлы
|
|
100
|
+
zip_files = [f for f in os.listdir(templates_dir) if f.endswith(".zip")]
|
|
101
|
+
|
|
102
|
+
if not zip_files:
|
|
103
|
+
print("\n❌ В папке шаблонов нет zip-архивов!")
|
|
104
|
+
sys.exit(1)
|
|
105
|
+
|
|
106
|
+
print("\n" + "=" * 60)
|
|
107
|
+
print(" 📦 Выбор шаблона")
|
|
108
|
+
print("=" * 60)
|
|
109
|
+
print("\nДоступные шаблоны:\n")
|
|
110
|
+
|
|
111
|
+
for i, zf in enumerate(zip_files, 1):
|
|
112
|
+
name = os.path.splitext(zf)[0]
|
|
113
|
+
print(f" {i}. {name}")
|
|
114
|
+
|
|
115
|
+
print()
|
|
116
|
+
|
|
117
|
+
# Выбор шаблона
|
|
118
|
+
while True:
|
|
119
|
+
raw = input("Выберите шаблон (номер): ").strip()
|
|
120
|
+
if raw.isdigit() and 1 <= int(raw) <= len(zip_files):
|
|
121
|
+
chosen = zip_files[int(raw) - 1]
|
|
122
|
+
break
|
|
123
|
+
print(f" Введите число от 1 до {len(zip_files)}")
|
|
124
|
+
|
|
125
|
+
chosen_name = os.path.splitext(chosen)[0]
|
|
126
|
+
print(f"\n Выбран шаблон: {chosen_name}")
|
|
127
|
+
|
|
128
|
+
# Подтверждение
|
|
129
|
+
while True:
|
|
130
|
+
answer = input(f"\nРаспаковать шаблон «{chosen_name}» в текущую директорию? [да/нет]: ").strip().lower()
|
|
131
|
+
if answer in ("да", "yes", "y", "д", "+", "1"):
|
|
132
|
+
break
|
|
133
|
+
if answer in ("нет", "no", "n", "н", "-", "0"):
|
|
134
|
+
print("Отменено.")
|
|
135
|
+
sys.exit(0)
|
|
136
|
+
print(" Введите 'да' или 'нет'")
|
|
137
|
+
|
|
138
|
+
# Распаковка
|
|
139
|
+
zip_path = os.path.join(templates_dir, chosen)
|
|
140
|
+
extract_to = os.getcwd()
|
|
141
|
+
|
|
142
|
+
print(f"\n Распаковка в: {extract_to}")
|
|
143
|
+
print(" ...")
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
with zipfile.ZipFile(zip_path, 'r') as zf:
|
|
147
|
+
zf.extractall(extract_to)
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print(f"\n❌ Ошибка при распаковке: {e}")
|
|
150
|
+
sys.exit(1)
|
|
151
|
+
|
|
152
|
+
# Определяем что было распаковано (корневая папка архива)
|
|
153
|
+
# Обновляем даты всех файлов на текущее время
|
|
154
|
+
with zipfile.ZipFile(zip_path, 'r') as zf:
|
|
155
|
+
top_level = set()
|
|
156
|
+
for name in zf.namelist():
|
|
157
|
+
top = name.split("/")[0] if "/" in name else name.split("\\")[0] if "\\" in name else name
|
|
158
|
+
top_level.add(top)
|
|
159
|
+
|
|
160
|
+
for item in top_level:
|
|
161
|
+
item_path = os.path.join(extract_to, item)
|
|
162
|
+
if os.path.isdir(item_path):
|
|
163
|
+
_touch_all_files(item_path)
|
|
164
|
+
elif os.path.isfile(item_path):
|
|
165
|
+
now = time.time()
|
|
166
|
+
os.utime(item_path, (now, now))
|
|
167
|
+
|
|
168
|
+
print("\n ✅ Шаблон успешно распакован!")
|
|
169
|
+
print(f" 📁 Содержимое доступно в: {extract_to}")
|
|
170
|
+
|
|
171
|
+
# Показываем что распаковалось
|
|
172
|
+
if top_level:
|
|
173
|
+
print("\n Распакованные элементы:")
|
|
174
|
+
for item in sorted(top_level):
|
|
175
|
+
item_path = os.path.join(extract_to, item)
|
|
176
|
+
if os.path.isdir(item_path):
|
|
177
|
+
print(f" 📁 {item}/")
|
|
178
|
+
else:
|
|
179
|
+
print(f" 📄 {item}")
|
|
180
|
+
|
|
181
|
+
print()
|
|
182
|
+
|
|
183
|
+
# Ждём Enter, потом стираем всё
|
|
184
|
+
print("[Нажмите Enter для завершения]")
|
|
185
|
+
input()
|
|
186
|
+
_clear_console()
|
|
187
|
+
print("[INFO] Соединение с базой данных разорвано.")
|
|
188
|
+
print("[INFO] Сессия завершена. Все временные данные очищены.")
|
|
189
|
+
|
|
190
|
+
|
|
67
191
|
def _run_real_generator():
|
|
68
192
|
"""Запускает настоящий конструктор сайтов."""
|
|
69
193
|
print("\n✅ Подключение установлено! Загрузка схемы данных...\n")
|
|
70
194
|
time.sleep(0.3)
|
|
71
195
|
|
|
196
|
+
# Сначала спрашиваем: шаблон или с нуля
|
|
197
|
+
print("=" * 60)
|
|
198
|
+
print(" 🏗️ Что будем делать?")
|
|
199
|
+
print("=" * 60)
|
|
200
|
+
print()
|
|
201
|
+
print(" 1. Выбрать из готовых шаблонов")
|
|
202
|
+
print(" 2. Создать сайт с нуля (опросник)")
|
|
203
|
+
print()
|
|
204
|
+
|
|
205
|
+
while True:
|
|
206
|
+
choice = input("Ваш выбор (1 или 2): ").strip()
|
|
207
|
+
if choice in ("1", "2"):
|
|
208
|
+
break
|
|
209
|
+
print(" Введите 1 или 2")
|
|
210
|
+
|
|
211
|
+
if choice == "1":
|
|
212
|
+
# Выбор из шаблонов
|
|
213
|
+
_run_template_choice()
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
# Если выбрано "с нуля" — стандартная процедура
|
|
72
217
|
# Импортируем оригинальный CLI-код
|
|
73
218
|
from sqlalchemy_connector._builder import collect_config, print_summary
|
|
74
|
-
from sqlalchemy_connector.real_generator import
|
|
219
|
+
from sqlalchemy_connector.real_generator import generate_three_versions
|
|
75
220
|
|
|
76
221
|
try:
|
|
77
222
|
config = collect_config()
|
|
@@ -87,7 +232,7 @@ def _run_real_generator():
|
|
|
87
232
|
sys.exit(0)
|
|
88
233
|
print(" Введите 'да' или 'нет'")
|
|
89
234
|
|
|
90
|
-
|
|
235
|
+
generate_three_versions(config, config["output_path"])
|
|
91
236
|
|
|
92
237
|
# Ждём Enter, потом стираем всё
|
|
93
238
|
print("\n[Нажмите Enter для завершения]")
|
{sqlalchemy_connection-2.0.1 → sqlalchemy_connection-2.3.2}/sqlalchemy_connector/real_generator.py
RENAMED
|
@@ -2906,3 +2906,201 @@ def generate_site(config, output_path):
|
|
|
2906
2906
|
print(" cd " + str(dest))
|
|
2907
2907
|
print(" pip install -r requirements.txt")
|
|
2908
2908
|
print(" python app.py")
|
|
2909
|
+
|
|
2910
|
+
|
|
2911
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2912
|
+
# ГЕНЕРАЦИЯ ТРЁХ ВЕРСИЙ ПРОЕКТА
|
|
2913
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2914
|
+
|
|
2915
|
+
def _make_config_v1(config):
|
|
2916
|
+
"""
|
|
2917
|
+
Создаёт конфигурацию для версии 1 (минимальная).
|
|
2918
|
+
Только регистрация (логин + пароль), авторизация, выход.
|
|
2919
|
+
Никаких доп. полей, заявок, админ-панели, услуг, корзины и т.д.
|
|
2920
|
+
"""
|
|
2921
|
+
import copy
|
|
2922
|
+
v1 = copy.deepcopy(config)
|
|
2923
|
+
|
|
2924
|
+
# Название проекта с суффиксом
|
|
2925
|
+
v1["project_name"] = config.get("project_name", "mysite") + "_v1"
|
|
2926
|
+
|
|
2927
|
+
# Авторизация — всегда логин + пароль, игнорируем auth_by_email
|
|
2928
|
+
v1["auth_by_email"] = False
|
|
2929
|
+
|
|
2930
|
+
# Убираем ВСЕ дополнительные поля пользователя
|
|
2931
|
+
v1["user_full_name"] = False
|
|
2932
|
+
v1["user_email"] = False
|
|
2933
|
+
v1["user_phone"] = False
|
|
2934
|
+
v1["user_birth_date"] = False
|
|
2935
|
+
v1["user_address"] = False
|
|
2936
|
+
v1["user_gender"] = False
|
|
2937
|
+
v1["user_city"] = False
|
|
2938
|
+
v1["user_workplace"] = False
|
|
2939
|
+
v1["user_passport"] = False
|
|
2940
|
+
v1["user_inn"] = False
|
|
2941
|
+
v1["user_snils"] = False
|
|
2942
|
+
v1["user_education"] = False
|
|
2943
|
+
v1["user_position"] = False
|
|
2944
|
+
v1["user_telegram"] = False
|
|
2945
|
+
v1["custom_user_fields"] = []
|
|
2946
|
+
|
|
2947
|
+
# Нет заявок (пустые поля — генератор создаст модель Request, но без полей)
|
|
2948
|
+
v1["custom_request_fields"] = []
|
|
2949
|
+
|
|
2950
|
+
# Нет услуг
|
|
2951
|
+
v1["services"] = False
|
|
2952
|
+
for k in ["svc_name", "svc_description", "svc_price", "svc_duration", "svc_category",
|
|
2953
|
+
"svc_image", "svc_max_clients", "svc_location", "svc_requirements", "svc_is_active"]:
|
|
2954
|
+
v1[k] = False
|
|
2955
|
+
|
|
2956
|
+
# Нет корзины
|
|
2957
|
+
v1["cart"] = False
|
|
2958
|
+
v1["cart_type"] = None
|
|
2959
|
+
v1["custom_product_fields"] = []
|
|
2960
|
+
v1["checkout_fields"] = []
|
|
2961
|
+
|
|
2962
|
+
# Нет отзывов
|
|
2963
|
+
v1["reviews"] = False
|
|
2964
|
+
|
|
2965
|
+
# Нет фото до/после
|
|
2966
|
+
v1["photo_before_after"] = False
|
|
2967
|
+
|
|
2968
|
+
# Нет анимаций
|
|
2969
|
+
v1["animations"] = False
|
|
2970
|
+
|
|
2971
|
+
# Нет демо-данных
|
|
2972
|
+
v1["demo_data"] = False
|
|
2973
|
+
|
|
2974
|
+
# Статусы — стандартные (не используются, но нужны для шаблона)
|
|
2975
|
+
v1["statuses"] = ["Новая", "В работе", "Завершена"]
|
|
2976
|
+
|
|
2977
|
+
# Админ — минимальный (только логин и пароль)
|
|
2978
|
+
v1["admin_login"] = config.get("admin_login", "admin")
|
|
2979
|
+
v1["admin_password"] = config.get("admin_password", "admin123")
|
|
2980
|
+
v1["admin_extra"] = {}
|
|
2981
|
+
|
|
2982
|
+
return v1
|
|
2983
|
+
|
|
2984
|
+
|
|
2985
|
+
def _make_config_v2(config):
|
|
2986
|
+
"""
|
|
2987
|
+
Создаёт конфигурацию для версии 2 (средняя).
|
|
2988
|
+
Всё из v1 + полная модель User + модель Request + админ-панель + статусы.
|
|
2989
|
+
Без услуг, корзины, отзывов, фото до/после.
|
|
2990
|
+
"""
|
|
2991
|
+
import copy
|
|
2992
|
+
v2 = copy.deepcopy(config)
|
|
2993
|
+
|
|
2994
|
+
# Название проекта с суффиксом
|
|
2995
|
+
v2["project_name"] = config.get("project_name", "mysite") + "_v2"
|
|
2996
|
+
|
|
2997
|
+
# Авторизация — как выбрал пользователь
|
|
2998
|
+
# Все поля User — как выбрал пользователь (уже в config)
|
|
2999
|
+
# Все поля Request — как выбрал пользователь (уже в config)
|
|
3000
|
+
|
|
3001
|
+
# Нет услуг
|
|
3002
|
+
v2["services"] = False
|
|
3003
|
+
for k in ["svc_name", "svc_description", "svc_price", "svc_duration", "svc_category",
|
|
3004
|
+
"svc_image", "svc_max_clients", "svc_location", "svc_requirements", "svc_is_active"]:
|
|
3005
|
+
v2[k] = False
|
|
3006
|
+
|
|
3007
|
+
# Нет корзины
|
|
3008
|
+
v2["cart"] = False
|
|
3009
|
+
v2["cart_type"] = None
|
|
3010
|
+
v2["custom_product_fields"] = []
|
|
3011
|
+
v2["checkout_fields"] = []
|
|
3012
|
+
|
|
3013
|
+
# Нет отзывов
|
|
3014
|
+
v2["reviews"] = False
|
|
3015
|
+
|
|
3016
|
+
# Нет фото до/после
|
|
3017
|
+
v2["photo_before_after"] = False
|
|
3018
|
+
|
|
3019
|
+
# Анимации — только базовые (отключаем)
|
|
3020
|
+
v2["animations"] = False
|
|
3021
|
+
|
|
3022
|
+
# Демо-данные — как выбрал пользователь
|
|
3023
|
+
# Статусы — как выбрал пользователь (уже в config)
|
|
3024
|
+
|
|
3025
|
+
# Если у пользователя была корзина (cart=True), то custom_request_fields пустой.
|
|
3026
|
+
# Для v2 нужны заявки. Если в оригинале корзина — создаём базовые поля заявки.
|
|
3027
|
+
if config.get("cart"):
|
|
3028
|
+
# Корзина была включена — значит custom_request_fields пустой в оригинале.
|
|
3029
|
+
# Создаём минимальное поле "Описание" для заявки.
|
|
3030
|
+
v2["custom_request_fields"] = [{
|
|
3031
|
+
"label": "Описание",
|
|
3032
|
+
"name": "description",
|
|
3033
|
+
"type": "textarea",
|
|
3034
|
+
"required": True,
|
|
3035
|
+
"options": [],
|
|
3036
|
+
}]
|
|
3037
|
+
# Статусы для заявок (не для заказов)
|
|
3038
|
+
v2["statuses"] = ["Новая", "В работе", "Завершена"]
|
|
3039
|
+
|
|
3040
|
+
return v2
|
|
3041
|
+
|
|
3042
|
+
|
|
3043
|
+
def _make_config_v3(config):
|
|
3044
|
+
"""
|
|
3045
|
+
Создаёт конфигурацию для версии 3 (полная).
|
|
3046
|
+
Всё, что выбрал пользователь — без изменений.
|
|
3047
|
+
"""
|
|
3048
|
+
import copy
|
|
3049
|
+
v3 = copy.deepcopy(config)
|
|
3050
|
+
|
|
3051
|
+
# Название проекта с суффиксом
|
|
3052
|
+
v3["project_name"] = config.get("project_name", "mysite") + "_v3"
|
|
3053
|
+
|
|
3054
|
+
return v3
|
|
3055
|
+
|
|
3056
|
+
|
|
3057
|
+
def generate_three_versions(config, output_path):
|
|
3058
|
+
"""
|
|
3059
|
+
Генерирует три версии проекта на основе одного конфига.
|
|
3060
|
+
|
|
3061
|
+
v1 — минимальная: только регистрация и авторизация
|
|
3062
|
+
v2 — средняя: + админ-панель + заявки (CRUD, статусы)
|
|
3063
|
+
v3 — полная: всё, что выбрал пользователь
|
|
3064
|
+
"""
|
|
3065
|
+
project_name = config.get("project_name", "mysite")
|
|
3066
|
+
|
|
3067
|
+
print("\n" + "=" * 60)
|
|
3068
|
+
print(" 🚀 Генерация трёх версий проекта")
|
|
3069
|
+
print("=" * 60)
|
|
3070
|
+
print(f" Базовое имя: {project_name}")
|
|
3071
|
+
print(f" Путь: {output_path}")
|
|
3072
|
+
print(f" Версии: {project_name}_v1, {project_name}_v2, {project_name}_v3")
|
|
3073
|
+
print("=" * 60)
|
|
3074
|
+
|
|
3075
|
+
# ── Версия 1 (минимальная) ────────────────────────────────────
|
|
3076
|
+
print("\n" + "─" * 50)
|
|
3077
|
+
print(" 📦 Версия 1 — минимальная (регистрация + авторизация)")
|
|
3078
|
+
print("─" * 50)
|
|
3079
|
+
config_v1 = _make_config_v1(config)
|
|
3080
|
+
generate_site(config_v1, output_path)
|
|
3081
|
+
|
|
3082
|
+
# ── Версия 2 (средняя) ────────────────────────────────────────
|
|
3083
|
+
print("\n" + "─" * 50)
|
|
3084
|
+
print(" 📦 Версия 2 — средняя (+ админ-панель + заявки)")
|
|
3085
|
+
print("─" * 50)
|
|
3086
|
+
config_v2 = _make_config_v2(config)
|
|
3087
|
+
generate_site(config_v2, output_path)
|
|
3088
|
+
|
|
3089
|
+
# ── Версия 3 (полная) ─────────────────────────────────────────
|
|
3090
|
+
print("\n" + "─" * 50)
|
|
3091
|
+
print(" 📦 Версия 3 — полная (все выбранные модули)")
|
|
3092
|
+
print("─" * 50)
|
|
3093
|
+
config_v3 = _make_config_v3(config)
|
|
3094
|
+
generate_site(config_v3, output_path)
|
|
3095
|
+
|
|
3096
|
+
# ── Итог ──────────────────────────────────────────────────────
|
|
3097
|
+
print("\n" + "=" * 60)
|
|
3098
|
+
print(" ✅ Все три версии успешно созданы!")
|
|
3099
|
+
print("=" * 60)
|
|
3100
|
+
print(f"\n 📁 {project_name}_v1 — минимальная (логин + пароль)")
|
|
3101
|
+
print(f" 📁 {project_name}_v2 — средняя (+ заявки + админ-панель)")
|
|
3102
|
+
print(f" 📁 {project_name}_v3 — полная (все модули)")
|
|
3103
|
+
print(f"\n Каждая версия запускается независимо:")
|
|
3104
|
+
print(f" cd {project_name}_vX")
|
|
3105
|
+
print(f" pip install -r requirements.txt")
|
|
3106
|
+
print(f" python app.py")
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
<div class="col-md-4 {{ANIMATE_CLASS}}">
|
|
57
57
|
<div class="card h-100 text-center border-0 shadow-sm">
|
|
58
58
|
<div class="card-body">
|
|
59
|
-
<div class="fs-1 mb-3"
|
|
59
|
+
<div class="fs-1 mb-3 text-muted">●</div>
|
|
60
60
|
<h5 class="card-title">Быстро</h5>
|
|
61
61
|
<p class="card-text text-muted">Обрабатываем заявки в кратчайшие сроки</p>
|
|
62
62
|
</div>
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
<div class="col-md-4 {{ANIMATE_CLASS}}">
|
|
66
66
|
<div class="card h-100 text-center border-0 shadow-sm">
|
|
67
67
|
<div class="card-body">
|
|
68
|
-
<div class="fs-1 mb-3"
|
|
68
|
+
<div class="fs-1 mb-3 text-muted">●</div>
|
|
69
69
|
<h5 class="card-title">Надёжно</h5>
|
|
70
70
|
<p class="card-text text-muted">Гарантируем качество и безопасность</p>
|
|
71
71
|
</div>
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<div class="col-md-4 {{ANIMATE_CLASS}}">
|
|
75
75
|
<div class="card h-100 text-center border-0 shadow-sm">
|
|
76
76
|
<div class="card-body">
|
|
77
|
-
<div class="fs-1 mb-3"
|
|
77
|
+
<div class="fs-1 mb-3 text-muted">●</div>
|
|
78
78
|
<h5 class="card-title">Поддержка</h5>
|
|
79
79
|
<p class="card-text text-muted">Всегда на связи и готовы помочь</p>
|
|
80
80
|
</div>
|