[英]sqlalchemy use of inheritance in postgres
in an attempt to learn sqlalchemy (and python), i am trying to duplicate an already existing project, but am having trouble figuring out sqlalchemy and inheritance with postgres.为了学习 sqlalchemy(和 python),我正在尝试复制一个已经存在的项目,但是在使用 postgres 找出 sqlalchemy 和 inheritance 时遇到了麻烦。
here is an example of what our postgres database does (obviously, this is simplified):这是我们的 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);
And then the inserts would be done with a trigger, so that they were properly inserted into the child databases.然后插入将使用触发器完成,以便将它们正确插入到子数据库中。 Something like:
就像是:
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;
in summary, i have a parent table with a foreign key to another table.总之,我有一个父表,其外键指向另一个表。 then i have 2 child tables that exist, and the inserts are done based upon a given value.
然后我有 2 个子表存在,并且插入是基于给定值完成的。 in my example above, if file_entry_system_name is 'ops', then the row goes into the ops_file_entry table;
在我上面的示例中,如果 file_entry_system_name 是“ops”,则该行进入 ops_file_entry 表; 'eng' goes into eng_file_entry_table.
'eng' 进入 eng_file_entry_table。 we have hundreds of children tables in our production environment, and considering the amount of data, it really speeds things up, so i would like to keep this same structure.
我们的生产环境中有数百个子表,考虑到数据量,它确实加快了速度,所以我想保持这个相同的结构。 i can query the parent, and as long as i give it the right 'system_name', it immediately knows which child table to look into.
我可以查询父表,只要我给它正确的“system_name”,它就会立即知道要查看哪个子表。
my desire is to emulate this with sqlalchemy, but i can't find any examples that go into this much detail.我的愿望是用 sqlalchemy 来模拟这个,但我找不到任何例子可以说明 go 如此详细。 i look at the sql generated by sqlalchemy by examples, and i can tell it is not doing anything similar to this on the database side.
我通过示例查看了由 sqlalchemy 生成的 sql 示例,我可以看出它在数据库端没有做任何类似的事情。
the best i can come up with is something like:我能想到的最好的方法是:
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'}
in the end, what am i missing?最后,我错过了什么? how do i tell sqlalchemy to associate anything that is inserted into FileEntry with a system name of 'ops' to go to the 'ops_file_entry' table?
我如何告诉 sqlalchemy 将插入到 FileEntry 的任何内容与系统名称为“ops”的 go 关联到“ops_file_entry”表? is my understanding way off?
我的理解有问题吗?
some insight into what i should do would be amazing.对我应该做什么的一些见解会很棒。
You just create a new instance of ops_file_entry
(shouldn't this be OpsFileEntry
?), add it into the session, and upon flush, one row will be inserted into table file_entry
as well as table ops_file_entry
.您只需创建一个新的
ops_file_entry
实例(这不应该是OpsFileEntry
吗?),将其添加到 session 中,在刷新时,一行将插入到表file_entry
以及表ops_file_entry
中。
You don't need to set the file_entry_system_name
attribute, nor the trigger.您不需要设置
file_entry_system_name
属性,也不需要设置触发器。
I don't really know python or sqlalchemy, but I figured I'd give it a shot for old times sake.我真的不知道 python 或 sqlalchemy,但我想我会为过去的缘故试一试。 ;)
;)
Have you tried basically setting up your own trigger at the application level?您是否尝试过在应用程序级别设置自己的触发器? Something like this might work:
像这样的东西可能会起作用:
from sqlalchemy import event, orm
def my_after_insert_listener(mapper, connection, target):
# set up your constraints to store the data as you want
if target.file_entry_system_name = 'eng'
# do your child table insert
elseif target.file_entry_system_name = 'ops'
# do your child table insert
#…
mapped_file_entry_class = orm.mapper(FileEntry, 'file_entry')
# associate the listener function with FileEntry,
# to execute during the "after_insert" hook
event.listen(mapped_file_entry_class, 'after_insert', my_after_insert_listener)
I'm not positive, but I think target
(or perhaps mapper
) should contain the data being inserted.我不是很肯定,但我认为
target
(或者可能是mapper
)应该包含正在插入的数据。
Events (esp. after_create) and mapper will probably be helpful. 事件(尤其是 after_create)和映射器可能会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.