sqlalchemy外键/查询连接

时间:2012-05-06 19:33:28

标签: python orm sqlalchemy pyramid

我在sqlalchemy中使用外键时出现问题,而不是自动递增主键ID

我使用:python 2.7,pyramid 1.3和sqlalchemy 0.7

这是我的模特

class Page(Base):
    __tablename__ = 'page'
    id = Column(Integer, ForeignKey('mapper.object_id'), autoincrement=True, primary_key=True)
    title = Column(String(30), unique=True)
    title_slug = Column(String(75), unique=True)
    text = Column(Text)
    date_added = Column(DateTime)

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column(String(100), unique=True)
    email = Column(String(100), unique=True)
    password = Column(String(100))

class Group(Base):
    __tablename__ = 'groups'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), unique=True)

class Member(Base):
    __tablename__ = 'members'

    user_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
    group_id = Column(Integer, ForeignKey('groups.id'), primary_key=True)

class Resource(Base):
    __tablename__ = 'resource'

    id = Column(Integer, primary_key=True)
    tablename = Column(Text)
    action = Column(Text)

class Mapper(Base):
    __tablename__ = 'mapper'

    resource_id = Column(Integer, ForeignKey('resource.id'), primary_key=True)
    group_id = Column(Integer, ForeignKey('groups.id'), primary_key=True)
    object_id = Column(Integer, primary_key=True)

这是我在SQLAlchemys ORM中编写的RAW SQL查询

'''
SELECT g.name, r.action
FROM groups AS g
INNER JOIN resource AS r
ON m.resource_id = r.id
INNER JOIN page AS p
ON p.id = m.object_id
INNER JOIN mapper AS m
ON m.group_id = g.id
WHERE p.id = ? AND
r.tablename = ?;
'''
obj = Page
query = DBSession().query(Group.name, Resource.action)\
        .join(Mapper)\
        .join(obj)\
        .join(Resource)\
        .filter(obj.id == obj_id, Resource.tablename == obj.__tablename__).all()

原始SQL查询工作正常,没有Page和Mapper之间的任何关系,但SQLAlchemys ORM似乎需要一个ForeignKey链接才能加入它们。所以我决定将ForeignKey放在Page.id上,因为Mapper.object_id将链接到几个不同的表。

这使得带有连接的SQL ORM查询按预期工作,但向Page表添加新数据会导致异常。

FlushError: Instance <Page at 0x3377c90> has a NULL identity key.  
If this is an auto-  generated value, check that the database 
table allows generation of new primary key values, and that the mapped 
Column object is configured to expect these generated values.  
Ensure also that this flush() is not occurring at an inappropriate time, 
such as within a load() event.

这是我的观看代码:

try:
    session = DBSession()
    with transaction.manager:
        page = Page(title, text)
        session.add(page)
        return HTTPFound(location=request.route_url('home'))
except Exception as e:
    print e
    pass
finally:
    session.close()

我真的不知道为什么,但我宁愿在SQLalchemy中使用解决方案而不是使用RAW SQL,因为我正在为了学习目的而制作这个项目:)

1 个答案:

答案 0 :(得分:3)

我认为autoincrement=TrueForeignKey(...)并不能很好地发挥作用。

在任何情况下,join在没有任何ForeignKey的情况下工作,您只需在join(...)的第二个参数中指定join条件:

obj = Page
query = DBSession().query(Group.name, Resource.action)\
    .join(Mapper)\
    .join(Resource)\
    .join(obj, Resource.tablename == obj.__tablename__)\
    .filter(obj.id == obj_id)\
    .all()