Я использую значение по умолчанию для столбца, следуя совету в этом сообщении: SQLAlchemy устанавливает значение столбца по умолчанию в зависимости от ID , но, к сожалению, не работает. Вероятно, из-за того, что указанный столбец c и ссылочный столбец находятся в составных отношениях ForeignkeyConstaint с другой таблицей, поэтому я получаю ошибку «несоответствие внешнего ключа»: МЕТОД 1) Когда вставлено значение по умолчанию: (sqlite3.OperationalError) foreign несоответствие ключей - "obj" ссылается на "obj_map" [SQL: INSERT INTO obj (otype, otype_id) VALUES (?,?)] [параметры: ('thing',)]
МЕТОД 2) в обойти указанную выше ошибку. Я также пытался предоставить второй FK напрямую, но он также не работает (sqlite3.OperationalError) Несоответствие внешнего ключа - "obj" ссылается на "obj_map" [SQL: INSERT INTO obj (otype, otype_id) VALUES (? ,?)] [параметры: ('вещь', 2)]
вот код:
from sqlalchemy import (Column, Integer, String, create_engine,
ForeignKey, ForeignKeyConstraint)
# Table, MetaData
from sqlalchemy.orm import create_session, Session # mapper,
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import select # , func
from rsk_app.sgr.sgr_config import _gen_sqlite_str as sqliteuri
from sqlalchemy.interfaces import PoolListener
# %%
Base = declarative_base()
in_memory_db = True
def default_obj_id(context):
current_type = context.get_current_parameters()['otype']
statement = select(
[ObjMap.id]).where(ObjMap.__table__.c.label == current_type)
print('SQL STATEMENT ----->\n', str(statement))
return statement
class ObjMap(Base):
__tablename__ = 'obj_map'
id = Column(Integer, primary_key=True)
label = Column(String, nullable=False, unique=True)
parent_id = Column(Integer, ForeignKey('obj_map.id'), nullable=True)
schema = Column(String)
class Obj(Base):
__tablename__ = 'obj'
id = Column(Integer, primary_key=True)
otype = Column(String, nullable=False)
otype_id = Column(Integer, nullable=False, default=default_obj_id)
__mapper_args__ = {'polymorphic_on': otype}
__table_args__ = (
ForeignKeyConstraint(
['otype_id', 'otype'],
['obj_map.id', 'obj_map.label'],
name='uk_obj_type'),)
class Thing(Obj):
__tablename__ = 'thing'
id = Column(Integer, ForeignKey(Obj.id), primary_key=True)
info = Column(String)
__mapper_args__ = {'polymorphic_identity': 'thing'}
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
if in_memory_db:
db_full = r'sqlite://'
engine = create_engine(db_full, echo=True, listeners=[ForeignKeysListener()])
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
s = Session(engine)
s = create_session(bind=engine, autoflush=True, autocommit=False)
# %%
def save_obj(obj):
s.add(obj)
try:
s.commit()
except Exception as e:
s.rollback()
print('===============NOT SAVED=========\n', str(e))
base_obj = ObjMap(label='object', schema='schema1')
save_obj(base_obj)
thing_obj = ObjMap(label='thing', schema='schema3',
parent_id=base_obj.id)
save_obj(thing_obj)
# CASE 1 : Should get the id from default function
other_thing = Thing(info='this is OTHER thing')
save_obj(other_thing)
# CASE 2--> insert providing object id: Fails on composite FK insertion
one_thing = Thing(info='this is ONE thing', otype_id=thing_obj.id)
save_obj(one_thing)
s.close()