将SqlSoup与数据库视图一起使用时出错

时间:2011-06-09 00:09:32

标签: python sql postgresql sqlalchemy

我想将SqlSoup与包含视图的现有数据库一起使用。访问一个表是游泳,但访问一个视图会导致“PKNotFoundError:table'[viewname]'没有定义主键...”

我是否正确推断SqlSoup不适用于数据库视图(默认情况下,至少)?我一直无法在Google,SO或SqlAlchemy邮件列表中找到任何直接相关的内容。如果您遇到此问题,如果您想访问不可更新的视图,您将如何继续?我是SQLAlchemy和SQLSoup的新手。

这是一个具体的例子:

from sqlalchemy.ext.sqlsoup import SqlSoup
u = SqlSoup('postgresql+psycopg2://PUBLIC@unison-db.org:5432/unison')
seq = u.pseq.filter(u.pseq.pseq_id==76).all() # okay
aliases = u.pseqalias.filter(u.pseqalias.pseq_id==76).all()

这是一个公共数据库。您可以使用psql运行等效查询:

psql -h unison-db.org -U PUBLIC -d unison -c 'select * from pseq where pseq_id=76'
psql -h unison-db.org -U PUBLIC -d unison -c 'select * from pseqalias where pseq_id=76'

3 个答案:

答案 0 :(得分:3)

感谢兰迪的地图()提示。这是一个完整的解决方案,您可以逐字尝试(数据库是公开的):

from sqlalchemy.ext.sqlsoup import SqlSoup
from sqlalchemy import Table
u = SqlSoup('postgresql+psycopg2://PUBLIC@unison-db.org:5432/unison')
pa_t = Table("palias", u._metadata, autoload=True, schema='unison')
pa = u.map(pa_t,primary_key=[pa_t.c.pannotation_id])
pa.slice(0,20).all()

这是Python 2.7.1,Alchemy 0.7.2。

有关参考资料,请参阅:

答案 1 :(得分:1)

Michael Bayer:

  

您需要传递列才能被视为其中的一部分   底层映射器的主键,使用sqlsoup.map_to(),但是   遗憾的是,目前还没有一个简单的界面,   因为你需要Table对象来获取列。所以   直到这个界面可以改进,现在它看起来像:

     

metadata = u._metadata t =表(“pseqaliases”,元数据,   自动加载= TRUE)

     

u.map_to(“pseqaliases”,selectable = t,   mapper_args = {“primary_key”:[t.c.col1,t.c.col2]})

     

这只是mapper的“primary_key”参数,有一些   http://www.sqlalchemy.org/docs/orm/mapper_config.html附近的例子   顶部。

http://groups.google.com/group/sqlalchemy/browse_thread/thread/fc1e8d079e10bac8

我尝试了map_to()方法,但仍然收到了PK错误。但是,以下方法运行良好:

ss = SqlSoup(db.engine)
meta = ss._metadata
tbl_vrmf = sa.Table("vRMF", meta, autoload=True)
vrmf_pks = [tbl_vrmf.c.dateId, tbl_vrmf.c.ident, tbl_vrmf.c.mnum]
vrmf = ss.map(tbl_vrmf, primary_key=vrmf_pks)

答案 2 :(得分:0)

像这样(未经测试):

from sqlalchemy import sql
from sqlalchemy.ext.sqlsoup import SqlSoup

u = SqlSoup('postgresql+psycopg2://PUBLIC@unison-db.org:5432/unison')

pseq_id = sql.column('pseq_id')
aliases = u.bind.execute(sql.select([pseq_id, '*'], from_obj=['pseqalias'])\
                .where(pseq_id==76)).fetchall()

当然你可以做到:

aliases = u.bind.execute('select * from pseqalias where pseq_id=76').fetchall()

...但在这种情况下,您失去了可重用性。