Skip to content

Commit ba09b1e

Browse files
Исправление ошибок с асинхронной БД и путями accounts
- Исправлена ошибка greenlet_spawn в makemigrations: добавлено преобразование асинхронных URL в синхронные для management команд - Исправлен метод _get_existing_tables для использования inspect вместо db.execute - Обновлены пути accounts: убран префикс /auth, теперь используется /accounts/login - Обновлены все редиректы и ссылки в шаблонах - Исправлена проблема с status.HTTP_303_SEE_OTHER (заменено на числовое значение 303)
1 parent d0b3c38 commit ba09b1e

File tree

8 files changed

+37
-26
lines changed

8 files changed

+37
-26
lines changed

src/raystack/conf/global_settings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,11 @@ def gettext_noop(s):
535535

536536
AUTHENTICATION_BACKENDS = ["raystack.contrib.auth.backends.ModelBackend"]
537537

538-
LOGIN_URL = "/auth/accounts/login/"
538+
LOGIN_URL = "/accounts/login/"
539539

540540
LOGIN_REDIRECT_URL = "/accounts/profile/"
541541

542-
LOGOUT_REDIRECT_URL = "/auth/accounts/login/"
542+
LOGOUT_REDIRECT_URL = "/accounts/login/"
543543

544544
# The number of seconds a password reset link is valid for (default: 3 days).
545545
PASSWORD_RESET_TIMEOUT = 60 * 60 * 24 * 3

src/raystack/contrib/auth/accounts/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ async def login_post(request: Request):
7272
# Generate JWT token
7373
token = generate_jwt(user.id)
7474

75-
response = RedirectResponse(url="/admin/", status_code=status.HTTP_303_SEE_OTHER)
75+
response = RedirectResponse(url="/admin/", status_code=303)
7676
response.set_cookie(key="jwt", value=token, httponly=True) # Secure cookie
7777
return response
7878
else:
79-
return RedirectResponse(url="/accounts/login?error=invalid_credentials", status_code=status.HTTP_303_SEE_OTHER)
79+
return RedirectResponse(url="/accounts/login?error=invalid_credentials", status_code=303)
8080

8181

8282
@router.get("/register", response_model=None)

src/raystack/contrib/templates/admin/includes/navigation-fullscreen.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</a>
2727
</li>
2828
<li class="nav-item">
29-
<a class="nav-link me-2" href="{{url_for('auth/accounts/register')}}">
29+
<a class="nav-link me-2" href="{{url_for('accounts/register')}}">
3030
<i class="fas fa-user-circle opacity-6 me-1"></i>
3131
Sign Up
3232
</a>

src/raystack/contrib/templates/admin/includes/navigation.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ <h6 class="font-weight-bolder mb-0">{{segment}}</h6>
2424
</button>
2525
</li>
2626
<!-- <li class="nav-item d-flex align-items-center">
27-
<a href="{{url_for('auth/accounts/login')}}" class="nav-link text-body font-weight-bold px-0">
27+
<a href="{{url_for('accounts/login')}}" class="nav-link text-body font-weight-bold px-0">
2828
<i class="fa fa-user me-sm-1"></i>
2929
<span class="d-sm-inline d-none me-3">Sign In</span>
3030
</a>

src/raystack/contrib/templates/admin/includes/scripts.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
sessionStorage.removeItem('auth_token');
1414

1515
// Redirect to login page
16-
window.location.href = '/auth/accounts/login';
16+
window.location.href = '/accounts/login';
1717
}
1818
</script>

src/raystack/contrib/templates/admin/includes/sidebar.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ <h6 class="ps-4 ms-2 text-uppercase text-xs font-weight-bolder opacity-6">Admin<
7676
</a>
7777
</li>
7878
<!-- <li class="nav-item">
79-
<a class="nav-link " href="{{url_for('auth/accounts/login')}}">
79+
<a class="nav-link " href="{{url_for('accounts/login')}}">
8080
<div class="icon icon-shape icon-sm shadow border-radius-md bg-white text-center me-2 d-flex align-items-center justify-content-center">
8181
<svg width="12px" height="12px" viewBox="0 0 40 44" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
8282
<title>document</title>

src/raystack/core/database/sqlalchemy.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,30 @@ def initialize(self):
5454
"""Initialize database connection."""
5555
if self._initialized:
5656
return
57+
58+
# Convert async URL to sync URL for synchronous operations
59+
sync_url = self.database_url
60+
if self.is_async_url():
61+
# Convert async URLs to sync URLs
62+
if '+aiosqlite://' in sync_url:
63+
sync_url = sync_url.replace('sqlite+aiosqlite://', 'sqlite://')
64+
elif '+asyncpg://' in sync_url:
65+
sync_url = sync_url.replace('postgresql+asyncpg://', 'postgresql://')
66+
elif '+aiomysql://' in sync_url:
67+
sync_url = sync_url.replace('mysql+aiomysql://', 'mysql://')
68+
elif '+asyncmy://' in sync_url:
69+
sync_url = sync_url.replace('mysql+asyncmy://', 'mysql://')
5770

5871
# Create engine
59-
if self.database_url.startswith('sqlite://'):
72+
if sync_url.startswith('sqlite://'):
6073
# For SQLite use StaticPool for better compatibility
6174
self.engine = create_engine(
62-
self.database_url,
75+
sync_url,
6376
poolclass=StaticPool,
6477
connect_args={"check_same_thread": False}
6578
)
6679
else:
67-
self.engine = create_engine(self.database_url)
80+
self.engine = create_engine(sync_url)
6881

6982
# Create session factory
7083
self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self.engine)

src/raystack/core/management/commands/makemigrations.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ def handle(self, *args, **options):
5454
# Initialize migration system if needed
5555
migration_manager.init()
5656

57-
# Initialize database if needed
57+
# Force synchronous mode for migrations
58+
# Initialize database if needed (sync mode)
5859
if hasattr(db, 'initialize') and not db._initialized:
5960
db.initialize()
6061

@@ -162,21 +163,18 @@ def handle(self, *args, **options):
162163
def _get_existing_tables(self):
163164
"""Gets a list of existing tables in the database"""
164165
try:
166+
# Ensure database is initialized in sync mode
167+
if not db._initialized:
168+
db.initialize()
169+
165170
if hasattr(db, 'engine') and db.engine:
166-
# For SQLAlchemy
167-
with db.engine.connect() as connection:
168-
if db.engine.dialect.name == 'sqlite':
169-
result = connection.execute("SELECT name FROM sqlite_master WHERE type='table'")
170-
elif db.engine.dialect.name == 'postgresql':
171-
result = connection.execute("SELECT tablename FROM pg_tables WHERE schemaname='public'")
172-
elif db.engine.dialect.name == 'mysql':
173-
result = connection.execute("SHOW TABLES")
174-
else:
175-
# For other databases use general approach
176-
result = connection.execute("SELECT table_name FROM information_schema.tables WHERE table_schema='public'")
177-
178-
tables = [row[0] for row in result.fetchall()]
179-
return tables
171+
# Use direct SQLAlchemy connection to avoid async/sync issues
172+
from sqlalchemy import text, inspect
173+
174+
# Use inspector for better compatibility
175+
inspector = inspect(db.engine)
176+
tables = inspector.get_table_names()
177+
return tables
180178
return []
181179
except Exception as e:
182180
self.stdout.write(

0 commit comments

Comments
 (0)