SQLAlchemy instantiate object from ORM fails with AttributeError: mapper
Question: I've been trying to get a decent-sized project going with SQLAlchemy on the
backend. I have table models across multiple files, a declarative base in its
own file, and a helper file to wrap common SQLAlchemy functions, and driver
file.

I was uploading data, then decided to add a column. Since this is just test
data I thought it'd be simplest to just drop all of the tables and start
fresh... then when I tried to recreate the schema and tables, the common
declarative base class suddenly had empty metadata. I worked around this by
importing the class declaration files -- strange, since I didn't need those
imports before -- and it was able to recreate the schema successfully.

But now when I try to create objects again, I get an error:

    
    
    AttributeError: mapper
    

Now I'm totally confused! Can someone explain what's happening here? It was
working fine before I dropped the schema and now I can't get it working.

Here's the skeleton of my setup:

**base.py**

    
    
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    

**models1.py**

    
    
    from base import Base
    class Business(Base):
        __tablename__ = 'business'
        id = Column(Integer, primary_key=True)
    

**models2.py:**

    
    
    from base import Base
    class Category(Base):
        __tablename__ = 'category'
        id = Column(Integer, primary_key=True)
    

**helper.py:**

    
    
    from base import Base
    
    # I didn't need these two imports the first time I made the schema
    # I added them after I was just getting an empty schema from base.Base
    # but have no idea why they're needed now?
    import models1
    import models2
    
    def setupDB():
        engine = getDBEngine(echo=True) # also a wrapped func (omitted for space)
        #instantiate the schema
        try:
            Base.metadata.create_all(engine, checkfirst=True)
            logger.info("Successfully instantiated Database with model schema")
        except:
            logger.error("Failed to instantieate Database with model schema")
            traceback.print_exc()
    
    def dropAllTables():
        engine = getDBEngine(echo=True)
        # drop the schema
        try:
            Base.metadata.reflect(engine, extend_existing=True)
            Base.metadata.drop_all(engine)
            logger.info("Successfully dropped all the database tables in the schema")
        except:
            logger.error("Failed to drop all tables")
            traceback.print_exc()
    

**driver.py:**

    
    
    import models1
    import models2
    
    # ^ some code to get to this point
    categories []
    categories.append(
                    models2.Category(alias=category['alias'],
                                     title=category['title']) # error occurs here
                    )
    

**stack trace: (for completeness)**

    
    
    File "./main.py", line 16, in <module>
    yelp.updateDBFromYelpFeed(fname)
      File "/Users/thomaseffland/Development/projects/health/pyhealth/pyhealth/data/sources/yelp.py", line 188, in updateDBFromYelpFeed
        title=category['title'])
      File "<string>", line 2, in __init__
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 347, in _new_state_if_none
        state = self._state_constructor(instance, self)
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 747, in __get__
        obj.__dict__[self.__name__] = result = self.fget(obj)
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 177, in _state_constructor
        self.dispatch.first_init(self, self.class_)
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/event/attr.py", line 256, in __call__
        fn(*args, **kw)
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2825, in _event_on_first_init
        configure_mappers()
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2721, in configure_mappers
        mapper._post_configure_properties()
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1710, in _post_configure_properties
        prop.init()
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 183, in init
        self.do_init()
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1616, in do_init
        self._process_dependent_arguments()
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1673, in     _process_dependent_arguments
        self.target = self.mapper.mapped_table
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 833, in __getattr__
        return self._fallback_getattr(key)
      File "/Users/thomaseffland/.virtualenvs/health/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 811, in _fallback_getattr
        raise AttributeError(key)
    AttributeError: mapper
    

I know this post is long, but I wanted to give the complete picture. First I
am confused why the `base.Base` schema was empty in the first place. Now I am
confused why the Categories object is missing a mapper!

Any help/insight/advice is greatly appreciated, thanks!

**Edit:**

So the model files and `helper.py` are in a supackage and the `driver.py` is
actually a file in a sibling subpackage and its code is wrapped in a function.
This driver function is called by a package-level main file. So I don't think
it can be because SQLAlchemy hasn't had time to initialize? (If I understand
the answer correctly) here is what the (relevant part of) main file looks
like:

**main.py:**

    
    
    import models.helper as helper
    helper.setupDB(echo=true) # SQLAlchemy echos the correct statements
    
    import driverpackage.driver as driver
    driver.updateDBFromFile(fname) # error occurs in here
    

and **driver.py** actually looks like:

    
    
    import ..models.models1
    import ..models.models2
    
    def updateDBFromFile(fname):
        # ^ some code to get to this point
        categories []
        categories.append(
                        models2.Category(alias=category['alias'],
                                         title=category['title']) # error occurs here
                        )
        # a bunch more code
    

**Edit 2:** I'm beginning to suspect the underlying issue is the same reason I
suddenly need to import all of the models to set up the schema in `helper.py`.
If I print the tables of the imported model objects, they have no bound
MetaData or schema:

    
    
    print YelpCategory.__dict__['__table__'].__dict__
    ####
    {'schema': None, '_columns': <sqlalchemy.sql.base.ColumnCollection object at 0x102312ef0>, 
    'name': 'yelp_category', 'description': 'yelp_category', 
    'dispatch': <sqlalchemy.event.base.DDLEventsDispatch object at 0x10230caf0>, 
    'indexes': set([]), 'foreign_keys': set([]), 
    'columns': <sqlalchemy.sql.base.ImmutableColumnCollection object at 0x10230fc58>, 
    '_prefixes': [], 
    '_extra_dependencies': set([]), 
    'fullname': 'yelp_category', 'metadata': MetaData(bind=None), 
    'implicit_returning': True, 
    'constraints': set([PrimaryKeyConstraint(Column('id', Integer(), table=<yelp_category>, primary_key=True, nullable=False))]), 'primary_key': PrimaryKeyConstraint(Column('id', Integer(), table=<yelp_category>, primary_key=True, nullable=False))}
    

I wonder why the metadata from the base that created the database is not
gettng bound?


Answer: I guess the error happens because you are executing your code on Python
module-level. This code is executed when Python imports the module.

  * Move your code to a function.

  * Call the function after SQLAlchemy has been properly initialized.

  * `create_all()` needs to call only once when the application is installed, because created tables persistent in the database

  * You need `DBSession.configure(bind=engine)` or related which will tell models to which database connection they are related. This is missing from the question.

