Создание и первичная инициализация базы даных успешно завершена. Наполнение демо-данными прошло без ошибок
This commit is contained in:
+1
-129
@@ -5,134 +5,6 @@ from .categories import *
|
||||
from .toolbox import *
|
||||
from .stock import *
|
||||
|
||||
from typing import Optional
|
||||
from sqlalchemy import inspect, text
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine
|
||||
from sqlalchemy.schema import CreateTable
|
||||
from utils import logger
|
||||
|
||||
# Импортируем все модели
|
||||
from db import Base
|
||||
from db.handlers import InitializeDatabase
|
||||
|
||||
|
||||
class DatabaseInitializer:
|
||||
existing_tables: Optional[list[str]] = None
|
||||
|
||||
def __init__(self, database_url: str):
|
||||
self.database_url = database_url
|
||||
self.engine: Optional[AsyncEngine] = None
|
||||
self.metadata = Base.metadata
|
||||
|
||||
async def initialize(self, force: bool = False, reNewDB: bool = False):
|
||||
"""Main database initialization method"""
|
||||
try:
|
||||
self.engine = create_async_engine(self.database_url)
|
||||
|
||||
async with self.engine.begin() as conn:
|
||||
if force:
|
||||
logger.info("Принудительное удаление и создание баз...")
|
||||
await self._drop_all()
|
||||
await self._create_tables_directly()
|
||||
await self._initialize_data()
|
||||
elif not await self._check_tables_exist(conn):
|
||||
logger.info("Не все необходимые таблицы существуют. Создаем...")
|
||||
await self._create_tables_directly()
|
||||
|
||||
# Проверяем после создания
|
||||
async with self.engine.begin() as conn:
|
||||
if not await self._check_tables_exist(conn):
|
||||
raise RuntimeError("Не все необходимые таблицы существуют!")
|
||||
|
||||
if reNewDB:
|
||||
logger.info("Принудительная загрузка данных...")
|
||||
await self._initialize_data()
|
||||
else:
|
||||
logger.info("Все необходимые таблицы существуют. Пропускаем...")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Инициализация базы завершилась ошибкой: {str(e)}")
|
||||
raise
|
||||
finally:
|
||||
if self.engine:
|
||||
await self.engine.dispose()
|
||||
|
||||
async def _check_tables_exist(self, conn) -> bool:
|
||||
"""Check if all tables from metadata exist"""
|
||||
try:
|
||||
DatabaseInitializer.existing_tables = await conn.run_sync(
|
||||
lambda sync_conn: inspect(sync_conn).get_table_names()
|
||||
)
|
||||
|
||||
required_tables = set(self.metadata.tables.keys())
|
||||
|
||||
if not required_tables:
|
||||
logger.error("Нет данных о таблицах в метаданных")
|
||||
return False
|
||||
|
||||
missing_tables = required_tables - set(DatabaseInitializer.existing_tables)
|
||||
if missing_tables:
|
||||
logger.warning("Существующие таблицы:")
|
||||
logger.info(DatabaseInitializer.existing_tables)
|
||||
logger.warning("Необходимые таблицы:")
|
||||
logger.info(required_tables)
|
||||
logger.warning("Отсутствующие таблицы:")
|
||||
logger.info(missing_tables)
|
||||
return False
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"Проверка таблиц завершилась ошибкой: {str(e)}")
|
||||
return False
|
||||
|
||||
async def _create_tables_directly(self):
|
||||
"""Create tables directly using SQLAlchemy (bypass Alembic)"""
|
||||
async with self.engine.begin() as conn:
|
||||
# Создаем все таблицы из метаданных
|
||||
for table in self.metadata.sorted_tables:
|
||||
try:
|
||||
if (
|
||||
DatabaseInitializer.existing_tables
|
||||
and table.name in DatabaseInitializer.existing_tables
|
||||
):
|
||||
logger.debug(
|
||||
f"Таблица {table.name} уже существует. Пропускаем..."
|
||||
)
|
||||
continue
|
||||
create_stmt = CreateTable(table)
|
||||
logger.info(f"Создаем таблицу: {table.name}")
|
||||
await conn.execute(create_stmt)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка создания таблицы: {str(e)}")
|
||||
logger.warning("Все таблицы успешно созданы")
|
||||
|
||||
async def _drop_all(self):
|
||||
"""Drop all tables"""
|
||||
async with self.engine.begin() as conn:
|
||||
# Получаем список всех таблиц
|
||||
existing_tables = await conn.run_sync(
|
||||
lambda sync_conn: inspect(sync_conn).get_table_names()
|
||||
)
|
||||
|
||||
for table in existing_tables:
|
||||
drop_stmt = text(
|
||||
f'DROP TABLE "{table}" CASCADE'
|
||||
) # Кавычки на случай спец. символов
|
||||
logger.info(f"Удаляем таблицу: {table}")
|
||||
await conn.execute(drop_stmt)
|
||||
|
||||
logger.warning("Все таблицы успешно удалены")
|
||||
|
||||
async def _initialize_data(self):
|
||||
"""Initialize required data"""
|
||||
try:
|
||||
logger.info("Инициализация данных...")
|
||||
await InitializeDatabase.initialize()
|
||||
logger.info("Данные успешно инициализированы")
|
||||
except Exception as e:
|
||||
logger.error(f"Инициализация данных завершилась ошибкой: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
__all__ = [
|
||||
"User",
|
||||
@@ -141,4 +13,4 @@ __all__ = [
|
||||
"Category",
|
||||
"Stock",
|
||||
"Toolkit",
|
||||
]
|
||||
]
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Boolean, Column, DateTime, Integer, String, Text
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -44,11 +44,7 @@ class AccessLevel(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(self, **kwargs):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(AccessLevel, self.id, **kwargs)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Column, DateTime, Integer, String, Text
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -21,11 +21,7 @@ class Category(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(id: int, **kwargs):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(Category, id, **kwargs)
|
||||
|
||||
+14
-10
@@ -1,7 +1,16 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, String, Text
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
Column,
|
||||
DateTime,
|
||||
Float,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
String,
|
||||
Text,
|
||||
)
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -28,18 +37,19 @@ class StocksRecords(Base):
|
||||
init_user_id = Column(
|
||||
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
accept_user_id = Column(
|
||||
decision_user_id = Column(
|
||||
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=True
|
||||
)
|
||||
reason = Column(Text, nullable=False)
|
||||
quantity = Column(Integer, nullable=False)
|
||||
price = Column(Float, nullable=False)
|
||||
accepted = Column(Boolean, default=None, nullable=True)
|
||||
edit_user_id = Column(
|
||||
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=True
|
||||
)
|
||||
edited = Column(JSONB, nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
accepted_at = Column(DateTime, nullable=True)
|
||||
decided_at = Column(DateTime, nullable=True)
|
||||
edited_at = Column(DateTime, nullable=True)
|
||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
|
||||
@@ -51,13 +61,9 @@ class StocksRecords(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(self, **kwargs):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(StocksRecords, self.id, **kwargs)
|
||||
|
||||
|
||||
@@ -77,6 +83,4 @@ class ServicesRecords(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
+11
-7
@@ -2,7 +2,7 @@ from datetime import datetime
|
||||
from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, String
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -14,13 +14,21 @@ class Stock(Base):
|
||||
Integer, ForeignKey("toolkits.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
toolkit_data = relationship(
|
||||
"Toolkit", cascade="all, delete-orphan", lazy="joined", uselist=False
|
||||
"Toolkit",
|
||||
cascade="all, delete-orphan",
|
||||
lazy="joined",
|
||||
uselist=False,
|
||||
single_parent=True,
|
||||
)
|
||||
toolbox_id = Column(
|
||||
Integer, ForeignKey("toolboxes.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
toolbox_data = relationship(
|
||||
"Toolbox", cascade="all, delete-orphan", lazy="joined", uselist=False
|
||||
"Toolbox",
|
||||
cascade="all, delete-orphan",
|
||||
lazy="joined",
|
||||
uselist=False,
|
||||
single_parent=True,
|
||||
)
|
||||
quantity = Column(Integer, nullable=False)
|
||||
price = Column(Float, nullable=False)
|
||||
@@ -36,11 +44,7 @@ class Stock(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(self, **kwargs):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(Stock, self.id, **kwargs)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String, Text
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -25,11 +25,7 @@ class Toolbox(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(id: int, **kwargs):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(Toolbox, id, **kwargs)
|
||||
|
||||
@@ -2,7 +2,7 @@ from datetime import datetime
|
||||
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Text
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.orm import relationship
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -15,7 +15,11 @@ class Toolkit(Base):
|
||||
specifications = Column(JSONB, default={})
|
||||
category_id = Column(Integer, ForeignKey("categories.id", ondelete="CASCADE"))
|
||||
category_data = relationship(
|
||||
"Category", cascade="all, delete-orphan", lazy="joined", uselist=False
|
||||
"Category",
|
||||
cascade="all, delete-orphan",
|
||||
lazy="joined",
|
||||
uselist=False,
|
||||
single_parent=True,
|
||||
)
|
||||
image = Column(JSONB)
|
||||
quantity_min = Column(Integer, nullable=True)
|
||||
@@ -34,11 +38,7 @@ class Toolkit(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(id: int, **kwargs):
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(Toolkit, id, **kwargs)
|
||||
|
||||
+1
-5
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String
|
||||
from db import Base
|
||||
from db import Base, CRUD
|
||||
import utils
|
||||
|
||||
|
||||
@@ -25,11 +25,7 @@ class User(Base):
|
||||
return utils.toDict(self)
|
||||
|
||||
async def save(self) -> "User":
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.create(self, refresh=True)
|
||||
|
||||
async def edit(self, **kwargs) -> "User":
|
||||
from db import CRUD
|
||||
|
||||
return await CRUD.update(User, self.id, **kwargs)
|
||||
|
||||
Reference in New Issue
Block a user