Sqlalchemy不认识外部编辑器中进行的手动更改

发布于 2025-02-13 12:32:43 字数 3416 浏览 0 评论 0原文

我注意到使用外部编辑器(例如 db浏览器)对我的sqlite数据库进行了任何更改。我的用例是,我需要检查和检索表中的唯一约束,该约束与以下代码合作:

mymodels.py包含我的表。考虑以下示例表:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class MyTable(Base):
    __tablename__ = "mytable"
    mytable_id = Column(Integer, primary_key=True)
    unique_col = Column(String, nullable=False, unique=True)

myutils.py包含用于创建会话的辅助功能。

from contextlib import contextmanager

def get_managed_session_maker(SessionMaker):

    @contextmanager
    def make_managed_session():
        session = SessionMaker()
        try:
            yield session
            session.commit()
        except Exception as e:
            session.rollback()
            raise RuntimeError(e)
        finally:
            session.close()
    
    return make_managed_session

db.py包含我的数据库逻辑。

from mymodels import Base
import myutils
from sqlalchemy import MetaData, inspect

class Database():
    def __init__(self, db_uri):
        self.db_uri = db_uri
        self.engine = sqlalchemy.create_engine(db_uri)
        Base.metadata.create_all(self.engine) # create tables

        Base.metadata.bind = self.engine
        SessionMaker = sessionmaker(bind=self.engine)
        self.ManagedSessionMaker = utils.get_managed_session_maker(SessionMaker)
        metadata = MetaData()
        metadata.reflect(bind=self.engine)
        self.metadata = metadata

    def get_unique_cols(self, table_name: str) -> list[str]:
        ...

        unique_cols = list()

        inspector = inspect(self.engine)
        tmp = inspector.get_unique_constraints(table_name)
        for unique in tmp:
            unique_cols.append(unique.get("column_names")[0])
        return unique_cols

在这种情况下,get_unique_cols功能将返回包含unique_col的列表为字符串。但是,如果我要手动删除唯一的约束,然后用外部编辑器(例如DB浏览器)手动添加它,那么我的功能将返回一个空列表,因此无法识别更改。有什么方法可以识别SQLalchemy中SQLite数据库的手动更改?

更新

,让我在混凝土表上说明我的问题。我创建了一个test.py脚本来创建一个新的引擎实例并打印出唯一的约束:

test.py

from sqlalchemy import create_engine, inspect

engine = create_engine("sqlite:///mydb.db")
  
inspector = inspect(engine)
uc = inspector.get_unique_constraints("_agegroups_10y")
print(uc)

首先,我让Sqlalchemy创建表_AGEGROUPS_10Y 在数据库浏览器中看起来像这样的代码>:

“在此处输入映像”

当我运行脚本而没有任何手动更改表的脚本时,我会得到输出如预期的:

$ python test.py 
[{'name': None, 'column_names': ['agegroup']}, {'name': None, 'column_names': ['unique_key']}]

现在,当我手动删除unique_key(或任何其他列)的唯一约束时...

...我得到一个空列表作为输出。

$ python test.py 
[]

因此,每次我手动更改唯一的约束时,我都会得到一个空列表...这对我来说是一个奇怪的行为,因为我至少期望获得与以前相同的输出。知道我做错了什么吗?

I have noticed that any changes made to my SQLite Database using an external editor such as DB Browser are not recognized by SQLAlchemy. My use case is, that i need to check and retrieve unique constraints in the table, which works fine with the following code:

mymodels.py contains my tables. Consider the following example table:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class MyTable(Base):
    __tablename__ = "mytable"
    mytable_id = Column(Integer, primary_key=True)
    unique_col = Column(String, nullable=False, unique=True)

myutils.py contains a helper function to create sessions.

from contextlib import contextmanager

def get_managed_session_maker(SessionMaker):

    @contextmanager
    def make_managed_session():
        session = SessionMaker()
        try:
            yield session
            session.commit()
        except Exception as e:
            session.rollback()
            raise RuntimeError(e)
        finally:
            session.close()
    
    return make_managed_session

db.py contains my database logic.

from mymodels import Base
import myutils
from sqlalchemy import MetaData, inspect

class Database():
    def __init__(self, db_uri):
        self.db_uri = db_uri
        self.engine = sqlalchemy.create_engine(db_uri)
        Base.metadata.create_all(self.engine) # create tables

        Base.metadata.bind = self.engine
        SessionMaker = sessionmaker(bind=self.engine)
        self.ManagedSessionMaker = utils.get_managed_session_maker(SessionMaker)
        metadata = MetaData()
        metadata.reflect(bind=self.engine)
        self.metadata = metadata

    def get_unique_cols(self, table_name: str) -> list[str]:
        ...

        unique_cols = list()

        inspector = inspect(self.engine)
        tmp = inspector.get_unique_constraints(table_name)
        for unique in tmp:
            unique_cols.append(unique.get("column_names")[0])
        return unique_cols

In this case, the get_unique_cols function would return a list containing unique_col as string. However, if i were to manually remove the unique constraint and then manually add it back with an external editor such as DB Browser, then my function returns an empty list, thus not recognizing the change. Is there any way to recognize manual changes to the SQLite Database in SQLAlchemy?

Update

So, let me illustrate my problem on a concrete table. I created a test.py script to create a new Engine instance and print out unique constraints:

test.py

from sqlalchemy import create_engine, inspect

engine = create_engine("sqlite:///mydb.db")
  
inspector = inspect(engine)
uc = inspector.get_unique_constraints("_agegroups_10y")
print(uc)

First, i let SQLAlchemy create the table _agegroups_10y which looks like this in the DB Browser:

enter image description here

When i run the script without any manual changes to the table, i get the output as expected:

$ python test.py 
[{'name': None, 'column_names': ['agegroup']}, {'name': None, 'column_names': ['unique_key']}]

Now when i manually delete the unique constraint for unique_key (or any other column)...

enter image description here

... i get an empty list as output.

$ python test.py 
[]

So everytime i manually change the unique constraint, i get an empty list back... This is a weird behavior to me, as i at least expected to get the same output as before. Any idea what i am doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文