Add SQLAlchemy and database boilerplate code
This commit is contained in:
parent
2da6e43797
commit
31df889dcb
15 changed files with 454 additions and 60 deletions
3
tofu_api/common/database/__init__.py
Normal file
3
tofu_api/common/database/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from .metadata import metadata_obj
|
||||
from .model import Model
|
||||
from .sqlalchemy import SQLAlchemy
|
||||
17
tofu_api/common/database/metadata.py
Normal file
17
tofu_api/common/database/metadata.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
from sqlalchemy import MetaData
|
||||
|
||||
__all__ = [
|
||||
'metadata_obj',
|
||||
]
|
||||
|
||||
# Define naming convention for constraints
|
||||
_naming_convention = {
|
||||
"ix": 'ix_%(column_0_label)s',
|
||||
"uq": "uq_%(table_name)s_%(column_0_name)s",
|
||||
"ck": "ck_%(table_name)s_%(constraint_name)s",
|
||||
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
|
||||
"pk": "pk_%(table_name)s"
|
||||
}
|
||||
|
||||
# Create global metadata object for database schemas
|
||||
metadata_obj = MetaData(naming_convention=_naming_convention)
|
||||
10
tofu_api/common/database/model.py
Normal file
10
tofu_api/common/database/model.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
from .metadata import metadata_obj
|
||||
|
||||
__all__ = [
|
||||
'Model',
|
||||
]
|
||||
|
||||
# Generate declarative base class for database models
|
||||
Model = declarative_base(name='Model', metadata=metadata_obj)
|
||||
87
tofu_api/common/database/sqlalchemy.py
Normal file
87
tofu_api/common/database/sqlalchemy.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
from typing import Optional, cast
|
||||
|
||||
from flask import Flask
|
||||
from sqlalchemy import MetaData, create_engine
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.orm import Session, scoped_session, sessionmaker
|
||||
|
||||
from .metadata import metadata_obj
|
||||
|
||||
__all__ = [
|
||||
'SQLAlchemy',
|
||||
]
|
||||
|
||||
|
||||
class SQLAlchemy:
|
||||
"""
|
||||
Wrapper class for integrating SQLAlchemy into the application as a Flask extension.
|
||||
"""
|
||||
_engine: Optional[Engine] = None
|
||||
_scoped_session: Optional[scoped_session] = None
|
||||
|
||||
def init_database(self, app: Flask):
|
||||
"""
|
||||
Initializes the SQLAlchemy engine.
|
||||
"""
|
||||
self._engine = self._create_engine()
|
||||
self._scoped_session = self._create_scoped_session()
|
||||
|
||||
@app.teardown_appcontext
|
||||
def shutdown_session(_exception=None):
|
||||
self._scoped_session.remove()
|
||||
|
||||
def _create_engine(self) -> Engine:
|
||||
"""
|
||||
Create the database engine using the app configuration.
|
||||
"""
|
||||
# TODO: Use config
|
||||
return create_engine('sqlite:////tmp/test.db')
|
||||
|
||||
def _create_scoped_session(self) -> scoped_session:
|
||||
"""
|
||||
Create a scoped session.
|
||||
"""
|
||||
return scoped_session(
|
||||
sessionmaker(
|
||||
autocommit=False,
|
||||
autoflush=False,
|
||||
bind=self._engine,
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def engine(self) -> Engine:
|
||||
"""
|
||||
Database engine.
|
||||
"""
|
||||
assert self._engine, 'Engine not ready yet.'
|
||||
return self._engine
|
||||
|
||||
@property
|
||||
def session(self) -> Session:
|
||||
"""
|
||||
Scoped database session.
|
||||
"""
|
||||
assert self._scoped_session, 'Session not ready yet.'
|
||||
# For all further purposes, the scoped session should be treated like a regular Session object.
|
||||
# Use cast() so we can use Session as the type annotation.
|
||||
return cast(Session, self._scoped_session)
|
||||
|
||||
@property
|
||||
def metadata(self) -> MetaData:
|
||||
"""
|
||||
Database metadata object.
|
||||
"""
|
||||
return metadata_obj
|
||||
|
||||
def create_all_tables(self) -> None:
|
||||
"""
|
||||
Create tables in the database for all models defined in the metadata.
|
||||
"""
|
||||
self.metadata.create_all(self.engine)
|
||||
|
||||
def drop_all_tables(self) -> None:
|
||||
"""
|
||||
Delete tables in the database for all models defined in the metadata.
|
||||
"""
|
||||
self.metadata.drop_all(self.engine)
|
||||
Loading…
Add table
Add a link
Reference in a new issue