postgresql - Use deferred reflection in SQLAlchemy 0.7 with cached metadata -
in project delaretive base deferred reflection being used.
from sqlalchemy import ( create_engine, table, column, integer, biginteger, text, datetime, numeric, string, ) sqlalchemy.dialects.postgresql import cidr sqlalchemy.orm import mapper, sessionmaker, relationship, backref sqlalchemy.orm.mapper import configure_mappers sqlalchemy.orm.util import _is_mapped_class sqlalchemy.pool import nullpool, queuepool sqlalchemy.ext.declarative import declarative_base, declared_attr sqlalchemy.schema import sequence sqlalchemy.ext.hybrid import hybrid_property # class taken sqlalchemy recipes class declarativereflectedbase(object): _mapper_args = [] @classmethod def __mapper_cls__(cls, *args, **kw): cls._mapper_args.append((args, kw)) @classmethod def prepare(cls, engine): while cls._mapper_args: args, kw = cls._mapper_args.pop() klass = args[0] if args[1] not none: table = args[1] table(table.name, cls.metadata, extend_existing=true, autoload_replace=false, autoload=true, autoload_with=engine, schema=table.schema) c in klass.__bases__: if _is_mapped_class(c): kw['inherits'] = c break klass.__mapper__ = mapper(*args, **kw) base = declarative_base() class reflected(declarativereflectedbase, base): __abstract__ = true class customer(reflected): @declared_attr def __tablename__(cls): return "customer" __table_args__ = {"schema": "schema_customer"} id = column('id', integer, primary_key=true) balances = relationship(lambda: balance, backref="customer") class balance(reflected): @declared_attr def __tablename__(cls): return "balance" __table_args__ = {"schema": "billing"} id = column('id', integer, primary_key=true) currency = relationship(lambda: currency) @hybrid_property def name_with_currency(self): return "{0} ({1})".format(self.name, self.currency.name_short) @name_with_curr.expression def name_with_curr_expr(cls): return cls.name + " (" + currency.name_short + ")" ....... # , other classes below def orm_initialization(engine): reflected.prepare(engine) # reflect db tables metadata s = sessionmaker() s = s(bind=engine) try: contetxs_count = s.query(contexts).count() # other classes difine not constant number of postgresql database contexts .... # call prepare again reflected.prepare(engine) finally: s.close() def sessionmaker_get(host, port, dbname, user, password, existing_engine=none, pooling=false): if existing_engine none: engine = create_engine( "{dialect}://{user}:{password}@{host}:{port}/{dbname}" .format(dialect="postgresql", **locals()), poolclass=nullpool, echo=false ) else: engine = existing_engine orm_initialization(engine) s = sessionmaker(bind=engine) return s
this works ok initialization of orm takes 7-8 seconds. so, want cache pickled metadata in file , load when create new sessionmaker. store metadata file on hdd , tried connect metadata reflected before first call prepare().
def orm_initialization(engine): import cpickle open('/tmp/metadata') meta_file: meta = cpickle.load(meta_file) meta.bind = engine reflected.metadata = meta reflected.prepare(engine) # reflect db tables metadata s = sessionmaker() s = s(bind=engine) ....
but error
argumenterror: not determine join condition between parent/child tables on relationship ... specify 'primaryjoin' expression. if 'secondary' present, 'secondaryjoin' needed well.
what doing wrong? how load pickled metadata correctly?
Comments
Post a Comment