3

嗨,我在 sqlalchemy 中遇到外键问题,不能在主键 ID 上自动递增

我正在使用:python 2.7、金字塔 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,因为我制作这个项目是为了学习:)

4

1 回答 1

4

我不认为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()
于 2012-05-07T11:04:38.050 回答