sqlalchemy在postgres中使用继承

jas*_*ose 6 python postgresql inheritance sqlalchemy polymorphic-associations

为了学习sqlalchemy(和python),我试图复制一个已经存在的项目,但是我很难用postgres搞清楚sqlalchemy和继承.

这是我们的postgres数据库的一个例子(显然,这是简化的):

CREATE TABLE system (system_id SERIAL PRIMARY KEY, 
                     system_name VARCHAR(24) NOT NULL);
CREATE TABLE file_entry(file_entry_id SERIAL, 
                        file_entry_msg VARCHAR(256) NOT NULL, 
                        file_entry_system_name VARCHAR(24) REFERENCES system(system_name) NOT NULL);
CREATE TABLE ops_file_entry(CONSTRAINT ops_file_entry_id_pkey PRIMARY KEY (file_entry_id), 
     CONSTRAINT ops_system_name_check CHECK ((file_entry_system_name = 'ops'::bpchar))) INHERITS (file_entry);
CREATE TABLE eng_file_entry(CONSTRAINT eng_file_entry_id_pkey PRIMARY KEY (file_entry_id),
     CONSTRAINT eng_system_name_check CHECK ((file_entry_system_name = 'eng'::bpchar)) INHERITS (file_entry);
CREATE INDEX ops_file_entry_index ON ops_file_entry USING btree (file_entry_system_id);
CREATE INDEX eng_file_entry_index ON eng_file_entry USING btree (file_entry_system_id);
Run Code Online (Sandbox Code Playgroud)

然后插入将使用触发器完成,以便它们正确插入子数据库.就像是:

CREATE FUNCTION file_entry_insert_trigger() RETURNS "trigger"
    AS $$
DECLARE 
BEGIN
     IF NEW.file_entry_system_name = 'eng' THEN
        INSERT INTO eng_file_entry(file_entry_id, file_entry_msg, file_entry_type, file_entry_system_name) VALUES (NEW.file_entry_id, NEW.file_entry_msg, NEW.file_entry_type, NEW.file_entry_system_name);
     ELSEIF NEW.file_entry_system_name = 'ops' THEN
        INSERT INTO ops_file_entry(file_entry_id, file_entry_msg, file_entry_type, file_entry_system_name) VALUES (NEW.file_entry_id, NEW.file_entry_msg, NEW.file_entry_type, NEW.file_entry_system_name);
     END IF;
     RETURN NULL;
 END;
 $$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

总之,我有一个父表与另一个表的外键.然后我有2个子表存在,插入是基于给定的值完成的.在上面的例子中,如果file_entry_system_name是'ops',那么该行进入ops_file_entry表; 'eng'进入eng_file_entry_table.我们在生产环境中有数百个子表,考虑到数据量,它确实加快了速度,所以我想保持这个相同的结构.我可以查询父级,只要我给它正确的'system_name',它就会立即知道要查看哪个子表.

我的愿望是用sqlalchemy模仿这个,但我找不到任何涉及这个细节的例子.我通过示例查看sqlalchemy生成的sql,我可以告诉它在数据库端没有做类似的事情.

我能想到的最好的是:

class System(_Base):
    __tablename__ = 'system'
    system_id = Column(Integer, Sequence('system_id_seq'), primary_key = True)
    system_name = Column(String(24), nullable=False)
    def __init(self, name)
        self.system_name = name
class FileEntry(_Base):
    __tablename__ = 'file_entry'
    file_entry_id = Column(Integer, Sequence('file_entry_id_seq'), primary_key=True)
    file_entry_msg = Column(String(256), nullable=False)
    file_entry_system_name = Column(String(24), nullable=False, ForeignKey('system.system_name'))
    __mapper_args__ = {'polymorphic_on': file_entry_system_name}
    def __init__(self, msg, name)
        self.file_entry_msg = msg
        self.file_entry_system_name = name
class ops_file_entry(FileEntry):
    __tablename__ = 'ops_file_entry'
    ops_file_entry_id = Column(None, ForeignKey('file_entry.file_entry_id'), primary_key=True)
    __mapper_args__ = {'polymorphic_identity': 'ops_file_entry'}
Run Code Online (Sandbox Code Playgroud)

最后,我错过了什么?我如何告诉sqlalchemy将插入到FileEntry中的任何内容与系统名称"ops"相关联以转到'ops_file_entry'表?我理解的方式是什么?

对我应该做什么的一些见解将是惊人的.

bos*_*nou 0

我不太了解 python 或 sqlalchemy,但我想我应该尝试一下。;)

\n\n

您是否尝试过在应用程序级别基本上设置自己的触发器?像这样的事情可能会起作用:

\n\n
from sqlalchemy import event, orm\n\ndef my_after_insert_listener(mapper, connection, target):\n    # set up your constraints to store the data as you want\n    if target.file_entry_system_name = \'eng\'\n        # do your child table insert\n \xc2\xa0 \xc2\xa0elseif target.file_entry_system_name = \'ops\'\n        # do your child table insert\n    #\xe2\x80\xa6\n\nmapped_file_entry_class = orm.mapper(FileEntry, \'file_entry\')\n# associate the listener function with FileEntry,\n# to execute during the "after_insert" hook\nevent.listen(mapped_file_entry_class, \'after_insert\', my_after_insert_listener)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我并不肯定,但我认为target(或者也许mapper)应该包含正在插入的数据。

\n\n

事件(尤其是 after_create)映射器可能会有所帮助。

\n