SQLAlchemy declarative syntax with autoload (reflection) in Pylons

I would like to use autoload to use an existing database. I know how to do this without declarative syntax (model / _init_.py):

def init_model(engine): """Call me before using any of the tables or classes in the model""" t_events = Table('events', Base.metadata, schema='events', autoload=True, autoload_with=engine) orm.mapper(Event, t_events) Session.configure(bind=engine) class Event(object): pass 

This works fine, but I would like to use declarative syntax:

 class Event(Base): __tablename__ = 'events' __table_args__ = {'schema': 'events', 'autoload': True} 

Unfortunately, this way I get:

sqlalchemy.exc.UnboundExecutionError: no engines are associated with this MetaData table. Pass the engine to the table through autoload_with = <someengine>, or associate MetaData with the engine through metadata.bind = <someengine>

The problem is that I do not know where to get the engine (use it in autoload_with) at the stage of importing the model (it is available in init_model ()). I tried adding

 meta.Base.metadata.bind(engine) 

for environment.py, but it does not work. Has anyone found some elegant solution?

+8
python reflection declarative sqlalchemy pylons
source share
3 answers

Well, I think I figured it out. The solution is to declare model objects outside of model/__init__.py . I came to the conclusion that __init__.py imported as the first file when importing something from a module (in this case, model ), and this causes problems, since model objects are declared before calling init_model() .

To avoid this, I created a new file in the model module, for example. objects.py . Then I declared all my model objects (e.g. Event ) in this file.

Then I can import my models as follows:

 from PRJ.model.objects import Event 

Also, to avoid specifying autoload-with for each table, I added this line at the end of init_model() :

 Base.metadata.bind = engine 

This way I can declare model objects without template code, for example:

 class Event(Base): __tablename__ = 'events' __table_args__ = {'schema': 'events', 'autoload': True} event_identifiers = relationship(EventIdentifier) def __repr__(self): return "<Event(%s)>" % self.id 
+10
source share

I just tried this using the orm module.

 Base = declarative_base(bind=engine) Base.metadata.reflect(bind=engine) 

Accessing tables manually or through a loop or something else:

 Base.metadata.sorted_tables 

May be helpful.

+1
source share

Check out the SQLAlchemy with Pylons tutorial on how to bind metadata to the engine in the init_model function.

If the meta.Base.metadata.bind(engine) statement successfully binds your model metadata to the engine, you can perform this initialization in your own init_model function. I think you did not want to skip the metadata binding in this function, right?

0
source share

Source: https://habr.com/ru/post/650425/


All Articles