删除没有级联到sqlalchemy中的表

时间:2011-12-29 11:07:32

标签: python sql orm foreign-keys sqlalchemy

我正在开发一个使用sqlalchemy 0.6的现有应用程序的扩展程序。

该应用程序已将sqlalchemy表创建为非声明性方式。我试图在我的扩展中创建一个新表,其中一个外键列指向应用程序数据库中主表的主键,我以声明方式创建它。

这一切都运行良好,加载扩展后创建表,并且完全没有任何投诉。我的表打印出来并证明新行已添加好了。 我想要和想到的可能(但不知道,因为我从未使用过sql或任何其他数据库)是删除了我的表中相应的行,当应用程序的主表中的行与相应的外键被删除

到目前为止,经过尝试的许多排列,没有任何效果。我认为使用backref集并且使用delete定义的关系是级联的,应该没有问题。因为新表是在一个只应该插件的扩展中定义的,所以我根本不想在主应用程序中编辑代码,至少这是我的目标。但是,我遇到的一个问题是,我想引用的主app表没有在其类中定义的成员变量,它没有在其映射器中声明其主键,并且只在表中声明了主键。这使得很难创建一个关系(ship)子句,其第一个参数必须是一个类或映射器(在这种情况下,它们都没有声明主键)。 有没有办法实现这个目标?

ps - 这是我正在使用的一些代码。 LocalFile是声明性类。所有连接细节都由主应用程序处理。

    if not self.LocalFile.__table__.exists(bind=Engine):
        self.LocalFile__table__.create(bind=Engine)

这是LocalFile类--Base是一个声明性基类,在构造函数中传递了bind = Engine:

   class LocalFile(Base):
    __tablename__ = 'local_file'
    _id = Column(Integer, Sequence('local_file_sequence', start=1, increment=1), primary_key=True)
    _filename = Column(String(50), nullable=False)
    _filepath = Column(String(128), nullable=False)
    _movieid = Column(Integer, ForeignKey(db.tables.movies.c.movie_id, onupdate='CASCADE', ondelete='CASCADE'))
    #movies = relation(db.Movie, backref="local_file", cascade="all")

    @property
    def filename(self):
        return self._filename

    @filename.setter
    def filename(self, filename):
        self._filename = filename

    @property
    def filepath(self):
        return self._filepath

    @filepath.setter
    def filepath(self, filepath):
        self._filepath = filepath

    @property
    def movieid(self):
        return self._movieid

    @movieid.setter
    def movieid(self, movieid):
        self._movieid = movieid

    @property
    def id(self):
        return self._id

    @id.setter
    def id(self, id):
        self._id = id

    filename = synonym('_filename', descriptor=filename)
    movieid = synonym('_movieid', descriptor=movieid)
    filepath = synonym('_filepath', descriptor=filepath)
    id = synonym('_id', descriptor=id)

    def __init__(self, filename, filepath, movieid):
        self._filename = filename
        self._filepath = filepath
        self._movieid = movieid

    def __repr__(self):
        return "<User('%s','%s', '%s')>" % (self.filename, self.filepath, self.movieid)

编辑:

后端是sqlite3。下面是使用echo命令生成的表的代码(感谢指出它,它非常有用 - 我怀疑现有应用程序生成的sql比必要的多得多)。 报告的sql表创建之后是删除行时生成的代码。我个人看不到任何引用可能删除本地文件表中的行的语句,但我现在知道很少的sql。谢谢。

     2011-12-29 16:29:18,530 INFO sqlalchemy.engine.base.Engine.0x...0650 
     CREATE TABLE local_file (
_id INTEGER NOT NULL, 
_filename VARCHAR(50) NOT NULL, 
_filepath VARCHAR(128) NOT NULL, 
_movieid INTEGER, 
PRIMARY KEY (_id), 
FOREIGN KEY(_movieid) REFERENCES movies (movie_id) ON DELETE CASCADE ON UPDATE CASCADE

    2011-12-29T16:29:18: I: sqlalchemy.engine.base.Engine.0x...0650(base:1387): 
    CREATE TABLE local_file (
_id INTEGER NOT NULL, 
_filename VARCHAR(50) NOT NULL, 
_filepath VARCHAR(128) NOT NULL, 
_movieid INTEGER, 
PRIMARY KEY (_id), 
FOREIGN KEY(_movieid) REFERENCES movies (movie_id) ON DELETE CASCADE ON UPDATE CASCADE

2011-12-29 16:29:18,534 INFO sqlalchemy.engine.base.Engine.0x...0650 ()
2011-12-29T16:29:18: I: sqlalchemy.engine.base.Engine.0x...0650(base:1388): ()
2011-12-29 16:29:18,643 INFO sqlalchemy.engine.base.Engine.0x...0650 COMMIT
2011-12-29T16:29:18: I: sqlalchemy.engine.base.Engine.0x...0650(base:1095): COMMIT
对于表中的行,

为两个表生成以下内容:

本地文件表: (,你'到Yuma') (,你'贪婪')

现有应用中的电影表: (,u'IMDb - 3:10到Yuma') (,u'Ravenous')

删除行时的代码太长了,以至于我不能在这里包含它(200行左右 - 删除一行不是太多了吗?),但它没有引用删除行中的一行localfile表。有这样的陈述:

   2011-12-29 17:09:17,141 INFO sqlalchemy.engine.base.Engine.0x...0650 UPDATE movies SET   poster_md5=?, updated=? WHERE movies.movie_id = ?
   2011-12-29T17:09:17: I: sqlalchemy.engine.base.Engine.0x...0650(base:1387): UPDATE movies SET poster_md5=?, updated=? WHERE movies.movie_id = ?
   2011-12-29 17:09:17,142 INFO sqlalchemy.engine.base.Engine.0x...0650 (None, '2011-12-29 17:09:17.141019', 2)
   2011-12-29T17:09:17: I: sqlalchemy.engine.base.Engine.0x...0650(base:1388): (None, '2011-12-29 17:09:17.141019', 2)
   2011-12-29 17:09:17,150 INFO sqlalchemy.engine.base.Engine.0x...0650 DELETE FROM posters WHERE posters.md5sum = ?
   2011-12-29T17:09:17: I: sqlalchemy.engine.base.Engine.0x...0650(base:1387): DELETE FROM posters WHERE posters.md5sum = ?
   2011-12-29 17:09:17,157 INFO sqlalchemy.engine.base.Engine.0x...0650 (u'083841e14b8bb9ea166ea4b2b976f03d',)

1 个答案:

答案 0 :(得分:9)

在SQLite中,您必须显式启用对外键的支持,否则它将忽略与外键相关的任何SQL。

engine = create_engine(database_url)

def on_connect(conn, record):
    conn.execute('pragma foreign_keys=ON')

from sqlalchemy import event
event.listen(engine, 'connect', on_connect)