внешние ключи/запросы sqlalchemy

Привет, у меня проблемы с внешним ключом в sqlalchemy, который не автоматически увеличивает идентификатор первичного ключа.

Я использую: 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)

и вот мой запрос RAW SQL, который я написал в SQLAlchemys ORM

'''
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, так как я делаю этот проект для учебных целей :)


person daniel    schedule 06.05.2012    source источник


Ответы (1)


Я не думаю, что autoincrement=True и ForeignKey(...) хорошо играют вместе.

В любом случае, чтобы 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()
person van    schedule 07.05.2012
comment
да, я только что добавил autoincrement=True, когда впервые начал получать нуль FlushError. попробую это, когда вернусь домой, и приму/задам дополнительные вопросы в зависимости от результата :) Но спасибо! - person daniel; 07.05.2012