sqlalchemy 外键/查询连接

dan*_*iel 3 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)
Run Code Online (Sandbox Code Playgroud)

这是我用 SQLAlchemys ORM 编写的原始 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()
Run Code Online (Sandbox Code Playgroud)

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

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

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.
Run Code Online (Sandbox Code Playgroud)

这是我的视图代码:

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()
Run Code Online (Sandbox Code Playgroud)

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

van*_*van 5

我不认为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()
Run Code Online (Sandbox Code Playgroud)