Replace db.Model with DeclarativeBase from SQLAlchemy for Flask-SQLAlchemy-Lite migration

This commit is contained in:
2026-04-06 01:49:44 +08:00
parent e6d25882fc
commit 9c6cc1f3eb
8 changed files with 49 additions and 24 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ from .base_account import init_base_accounts_command
from .currency import init_currencies_command
from .models import BaseAccount, Account
from .utils.title_case import title_case
from .utils.user import has_user, get_user_pk
from .utils.user import base_cls, has_user, get_user_pk
def __validate_username(ctx: click.core.Context, param: click.core.Option,
@@ -62,7 +62,7 @@ def __validate_username(ctx: click.core.Context, param: click.core.Option,
def init_db_command(username: str, skip_accounts: bool,
skip_currencies: bool) -> None:
"""Initializes the accounting database."""
db.create_all()
base_cls.metadata.create_all(db.engine)
init_base_accounts_command()
if not skip_accounts:
init_accounts_command(username)
+10 -10
View File
@@ -31,10 +31,10 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship
from . import db
from .locale import gettext
from .utils.user import user_cls, user_pk_column
from .utils.user import base_cls, user_cls, user_pk_column
class BaseAccount(db.Model):
class BaseAccount(base_cls):
"""A base account."""
__tablename__ = "accounting_base_accounts"
"""The table name."""
@@ -78,7 +78,7 @@ class BaseAccount(db.Model):
return [self.code, self.title_l10n] + [x.title for x in self.l10n]
class BaseAccountL10n(db.Model):
class BaseAccountL10n(base_cls):
"""A localized base account title."""
__tablename__ = "accounting_base_accounts_l10n"
"""The table name."""
@@ -95,7 +95,7 @@ class BaseAccountL10n(db.Model):
"""The localized title."""
class Account(db.Model):
class Account(base_cls):
"""An account."""
__tablename__ = "accounting_accounts"
"""The table name."""
@@ -354,7 +354,7 @@ class Account(db.Model):
return account
class AccountL10n(db.Model):
class AccountL10n(base_cls):
"""A localized account title."""
__tablename__ = "accounting_accounts_l10n"
"""The table name."""
@@ -371,7 +371,7 @@ class AccountL10n(db.Model):
"""The localized title."""
class Currency(db.Model):
class Currency(base_cls):
"""A currency."""
__tablename__ = "accounting_currencies"
"""The table name."""
@@ -483,7 +483,7 @@ class Currency(db.Model):
db.session.delete(self)
class CurrencyL10n(db.Model):
class CurrencyL10n(base_cls):
"""A localized currency name."""
__tablename__ = "accounting_currencies_l10n"
"""The table name."""
@@ -543,7 +543,7 @@ class JournalEntryCurrency:
return sum([x.amount for x in self.credit])
class JournalEntry(db.Model):
class JournalEntry(base_cls):
"""A journal entry."""
__tablename__ = "accounting_journal_entries"
"""The table name."""
@@ -661,7 +661,7 @@ class JournalEntry(db.Model):
db.session.delete(self)
class JournalEntryLineItem(db.Model):
class JournalEntryLineItem(base_cls):
"""A line item in the journal entry."""
__tablename__ = "accounting_journal_entry_line_items"
"""The table name."""
@@ -888,7 +888,7 @@ class JournalEntryLineItem(db.Model):
format_amount(self.amount)]
class Option(db.Model):
class Option(base_cls):
"""An option."""
__tablename__ = "accounting_options"
"""The table name."""
+2 -1
View File
@@ -22,9 +22,10 @@ This module should not import any other module from the application.
from secrets import randbelow
from .. import db
from ..utils.user import base_cls
def new_id(cls: type[db.Model]):
def new_id(cls: type[base_cls]):
"""Generates and returns a new, unused random ID for the data model.
:param cls: The data model.
+15 -4
View File
@@ -23,10 +23,10 @@ from abc import ABC, abstractmethod
import sqlalchemy as sa
from flask import g, Response
from flask_sqlalchemy.model import Model
from sqlalchemy.orm import DeclarativeBase
class UserUtilityInterface[T: Model](ABC):
class UserUtilityInterface[T: DeclarativeBase](ABC):
"""The interface for the user utilities."""
@abstractmethod
@@ -67,6 +67,14 @@ class UserUtilityInterface[T: Model](ABC):
:return: The response to require the user to log in.
"""
@property
@abstractmethod
def base(self) -> type[DeclarativeBase]:
"""Returns the base data model.
:return: The base data model.
"""
@property
@abstractmethod
def cls(self) -> type[T]:
@@ -109,7 +117,9 @@ class UserUtilityInterface[T: Model](ABC):
__user_utils: UserUtilityInterface
"""The user utilities."""
type user_cls = Model
base_cls = DeclarativeBase
"""The base data model."""
type user_cls = DeclarativeBase
"""The user class."""
user_pk_column: sa.Column = sa.Column(sa.Integer)
"""The primary key column of the user class."""
@@ -121,8 +131,9 @@ def init_user_utils(utils: UserUtilityInterface) -> None:
:param utils: The user utilities.
:return: None.
"""
global __user_utils, user_cls, user_pk_column
global __user_utils, base_cls, user_cls, user_pk_column
__user_utils = utils
base_cls = utils.base
user_cls = utils.cls
user_pk_column = utils.pk_column