Skip to content

Commit 3817739

Browse files
refactor(templates,project): restructure project templates and add async/sync variants
- Split project templates into async and sync versions - Reorganize app templates structure - Update example projects with new template structure - Improve project generation workflow - Add comprehensive development documentation
1 parent 03b4746 commit 3817739

File tree

157 files changed

+2269
-1498
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+2269
-1498
lines changed

DEVELOPMENT.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Raystack Development
2+
3+
## Running without installation
4+
5+
Raystack can be used without installing the library, just by cloning the repository.
6+
7+
### CLI Usage
8+
9+
To run management commands, use the `raystack.py` script in the project root:
10+
11+
```bash
12+
# Create synchronous project
13+
python3 raystack.py startproject myproject
14+
15+
# Create asynchronous project
16+
python3 raystack.py startproject myproject --async
17+
18+
# Create project without home app
19+
python3 raystack.py startproject myproject --no-home
20+
21+
# Create application
22+
python3 raystack.py startapp myapp
23+
24+
# View available commands
25+
python3 raystack.py help
26+
```
27+
28+
### Using created projects
29+
30+
Created projects can also work without installing the library. Their `manage.py` will automatically find raystack in the `src` folder:
31+
32+
```bash
33+
cd myproject
34+
python3 manage.py help
35+
python3 manage.py runserver
36+
```
37+
38+
## Library installation
39+
40+
For production use, it's recommended to install the library:
41+
42+
```bash
43+
pip install raystack
44+
```
45+
46+
After installation, you can use standard commands:
47+
48+
```bash
49+
raystack startproject myproject
50+
raystack startapp myapp
51+
```
52+
53+
## Project structure
54+
55+
```
56+
raystack/
57+
├── raystack.py # CLI script for development
58+
├── src/
59+
│ └── raystack/ # Main library code
60+
├── example/ # Synchronous project example
61+
├── example_async/ # Asynchronous project example
62+
└── test_projects/ # Test projects
63+
```
64+
65+
## Compatibility
66+
67+
- CLI script `raystack.py` works only for development
68+
- Created projects work both with installed library and without it
69+
- `manage.py` templates automatically determine the raystack installation method
70+
71+
## Fixed issues
72+
73+
### Database import errors
74+
75+
When running commands, Python 3.6 warnings may appear, but this is not critical:
76+
77+
```
78+
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/jwt/utils.py:7: CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography.
79+
```
80+
81+
These warnings do not affect command operation and will disappear when using a newer Python version.
82+
83+
### Lazy imports
84+
85+
All database module imports are now performed lazily (lazy imports), which allows:
86+
- Running commands without prior database configuration
87+
- Avoiding circular dependencies
88+
- Working both with installed library and without it

example/config/settings.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
DATABASES = {
88
'default': {
99
'ENGINE': 'raystack.core.database.sqlalchemy',
10-
# Синхронный режим (по умолчанию)
10+
# Synchronous mode (default)
1111
'URL': 'sqlite:///' + str(BASE_DIR / 'db.sqlite3'),
1212

13-
# Асинхронный режим (раскомментируйте для использования)
13+
# Asynchronous mode (uncomment to use)
1414
# 'URL': 'sqlite+aiosqlite:///' + str(BASE_DIR / 'db.sqlite3'),
1515

16-
# Другие примеры асинхронных URL:
16+
# Other examples of asynchronous URLs:
1717
# PostgreSQL: 'postgresql+asyncpg://user:pass@localhost/dbname'
1818
# MySQL: 'mysql+aiomysql://user:pass@localhost/dbname'
1919
}
@@ -45,7 +45,7 @@
4545

4646
STATIC_URL = "static/"
4747

48-
# Настройки статических файлов
48+
# Static files settings
4949
STATICFILES_DIRS = [
5050
str(BASE_DIR.parent / "src" / "raystack" / "contrib" / "static"),
5151
str(BASE_DIR / "static"),

example/core/__init__.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ class Settings(BaseSettings):
2020
database_url: str
2121
secret_key: str
2222
debug: bool
23-
youmoney_client_id: str | None = None # Добавьте эти поля, если они нужны
23+
youmoney_client_id: str | None = None # Add these fields if needed
2424
youmoney_redirect_url: str | None = None
2525
youmoney_client_secret: str | None = None
2626
youmoney_access_token: str | None = None
2727
youmoney_wallet_number: str | None = None
2828

2929
class Config:
30-
env_file = ".env" # Указывает путь к .env файлу
31-
extra = 'ignore' # Игнорировать лишние поля
30+
env_file = ".env" # Specifies path to .env file
31+
extra = 'ignore' # Ignore extra fields
3232

33-
# Инициализация объекта
33+
# Initialize object
3434
settings = Settings(
3535
database_url="postgresql://user:password@localhost/dbname",
3636
secret_key="your-secret-key",
@@ -53,7 +53,7 @@ async def not_found(request, exc):
5353
return RedirectResponse("/auth/accounts/login", status_code=303)
5454
# return render_template(request=request, template_name="401.html", context={"request": request})
5555

56-
# Класс для аутентификации
56+
# Authentication class
5757
class userAuthentication(AuthenticationBackend):
5858
async def authenticate(self, request):
5959
jwt_cookie = request.cookies.get('jwt')
@@ -66,7 +66,7 @@ async def authenticate(self, request):
6666
else:
6767
return # unauthenticated
6868

69-
# Middleware для отслеживания истории
69+
# Middleware for tracking history
7070
@app.middleware("http")
7171
async def update_session_history(request, call_next):
7272
response = await call_next(request)
@@ -75,25 +75,25 @@ async def update_session_history(request, call_next):
7575
return response
7676

7777

78-
# Middleware для работы с сессиями
78+
# Middleware for session management
7979
app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)
8080

81-
# Middleware для аутентификации
81+
# Middleware for authentication
8282
app.add_middleware(AuthenticationMiddleware, backend=userAuthentication())
8383

8484

8585
from apscheduler.schedulers.background import BackgroundScheduler
8686
from datetime import datetime
8787

88-
# # Функция, которая будет выполняться периодически
88+
# # Function that will be executed periodically
8989
# def periodic_task():
90-
# print(f"Периодическая задача выполнена: {datetime.now()}")
90+
# print(f"Periodic task completed: {datetime.now()}")
9191

92-
# # Инициализация планировщика
92+
# # Initialize scheduler
9393
# scheduler = BackgroundScheduler()
9494

95-
# # Добавление задачи для выполнения каждые 10 секунд
95+
# # Add task to execute every 10 seconds
9696
# scheduler.add_job(periodic_task, 'interval', seconds=10)
9797

98-
# # Запуск планировщика
98+
# # Start scheduler
9999
# scheduler.start()

example/templates/home/home.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{% extends "base.html" %}
22

33
{% block content %}
4-
<h1>Добро пожаловать в {{ framework }}!</h1>
5-
<p>Это простая домашняя страница.</p>
4+
<h1>Welcome to {{ framework }}!</h1>
5+
<p>This is a simple home page.</p>
66
{% endblock %}

example_async/apps/home/deps.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from fastapi import Depends
22
from sqlalchemy.ext.asyncio import AsyncSession
33

4-
# Используем функционал фреймворка для работы с базой данных
4+
# Use framework functionality for database operations
55
from raystack.core.database.base import get_async_db
66

7-
# Простая функция для получения текущего пользователя (заглушка)
7+
# Simple function for getting current user (placeholder)
88
async def get_current_user(session: AsyncSession = Depends(get_async_db)):
9-
# Здесь можно добавить логику аутентификации
9+
# Authentication logic can be added here
1010
return None
1111

example_async/apps/home/views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
from sqlalchemy.ext.asyncio import AsyncSession
44
from sqlmodel import select
55

6-
# Используем функционал фреймворка
6+
# Use framework functionality
77
from raystack.core.database.base import get_async_db
88
from .models import User
99

1010
async def home_view(request: Request, session: AsyncSession = Depends(get_async_db)):
1111
try:
12-
# Используем асинхронный синтаксис для SQLModel
12+
# Use asynchronous syntax for SQLModel
1313
result = await session.execute(select(User))
1414
users = result.scalars().all()
1515
user_count = len(users)
1616
except Exception as e:
17-
# Если база данных недоступна, показываем заглушку
17+
# If database is unavailable, show placeholder
1818
user_count = 0
1919
users = []
2020

example_async/config/settings.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
DATABASES = {
1111
'default': {
1212
'ENGINE': 'raystack.core.database.sqlalchemy',
13-
# Синхронный режим (для команд управления)
13+
# Synchronous mode (for management commands)
1414
# 'URL': 'sqlite:///' + str(BASE_DIR / 'db.sqlite3'),
1515

16-
# Асинхронный режим (для веб-сервера)
16+
# Asynchronous mode (for web server)
1717
'URL': 'sqlite+aiosqlite:///' + str(BASE_DIR / 'db.sqlite3'),
1818

19-
# Другие примеры асинхронных URL:
19+
# Other examples of asynchronous URLs:
2020
# PostgreSQL: 'postgresql+asyncpg://user:pass@localhost/dbname'
2121
# MySQL: 'mysql+aiomysql://user:pass@localhost/dbname'
2222
}
@@ -50,7 +50,7 @@
5050

5151
STATIC_URL = "static/"
5252

53-
# Настройки статических файлов
53+
# Static files settings
5454
STATICFILES_DIRS = [
5555
str(BASE_DIR.parent / "raystack" / "src" / "raystack" / "contrib" / "static"),
5656
str(BASE_DIR / "static"),

example_async/core/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from raystack import Raystack
22

3-
# Инициализация объекта
3+
# Initialize object
44
app = Raystack()

example_async/core/security.py

Lines changed: 0 additions & 30 deletions
This file was deleted.

example_async/templates/home.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8">
55

6-
<!-- Favicon для всех браузеров -->
6+
<!-- Favicon for all browsers -->
77
<link rel="icon" href="/static/favicon.ico" type="image/png">
88
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
99

0 commit comments

Comments
 (0)