我有一个数据库,其中有一个名为"项目":
import sqlite3
stmt = """CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT)"""
conn = sqlite3.connect('test20210101.db')
conn.execute(stmt)
我使用SQLAlchemy的自动映射功能将表映射到一个模型类:
import sqlalchemy as sa
from sqlalchemy.ext.automap import automap_base
engine = sa.create_engine('sqlite:///test20210101.db')
Base = automap_base()
Base.prepare(engine, reflect=True)
Item = Base.classes.items
但是,如果我尝试创建一个新项目,我会得到一个TypeError
:
>>> new_item = Item(name='foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: items() got an unexpected keyword argument 'name'
同样,尝试使用自动映射模型查询数据库失败:
>>> items = session.query(Item).all()
Traceback (most recent call last):
<lots of traceback>
sqlalchemy.exc.ArgumentError: Column expression or FROM clause expected, got ('items', <class 'sqlalchemy.ext.automap.items'>).
类似的代码适用于其他表,这里发生了什么?
正如TypeError
的提出所表明的那样,问题是Item
不是我们所期望的自动映射模型。实际上它是一个方法对象:
>>> type(Item)
<class 'method'>
>>> Item
<bound method Properties.items of <sqlalchemy.util._collections.Properties object at 0x7fb088f48fa0>>
问题是Base.classes
公开了类似于字典的API,而Base.classes.items
是API的items
方法,而不是自动映射的对象*。
至少有两种方法可以解决这个名称冲突:
使用
__getitem__
访问自动映射对象>>> Item = Base.classes['items'] >>> Item <class 'sqlalchemy.ext.automap.items'>
定义一个自定义函数,在准备
Base
时将表名映射到类名>>> def map_names(base, tablename, table): ... return 'my_items' if tablename == 'items' else tablename ... >>> Base = automap_base() >>> Base.prepare(engine, reflect=True, classname_for_table=map_names) >>> Item = Base.classes.my_items >>> Item <class 'sqlalchemy.ext.automap.my_items'>
*因此,其他与dict相关的名称也会出现同样的问题,例如keys
、values
等。
您导入的是文件,而不是类别Item
更改:
import Item
至
from Item import Item