1

I find it strange that people do not use dependency injection to manage their use of SQLAlchemy. According to the docs, one needs a reference to the table to perform db operations like inserts, but one only gets a reference to the table after it is created!

That means the db connection, db operations and table declarations must be done in the same file:

>>> from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
>>> conn = engine.connect()
>>> metadata = MetaData()
>>> users = Table('users', metadata,
...     Column('id', Integer, primary_key=True),
...     Column('name', String),
...     Column('fullname', String),
... )
>>> ins = users.insert()
>>> result = conn.execute(ins)

According to the snippet above, one needs the conn connection object, the users table object and the ins expression object to perform a complete transaction with the database. Unless some form of dependency injection is used, all three must be in the same file.

How have people structured their code to make this manageable?

3
  • 1
    you can store your Table objects in different module or even package and import it, why they should be in the same file? Commented May 25, 2017 at 16:49
  • Each time the file is imported the table will get created right? Commented May 25, 2017 at 18:05
  • no, module objects are created on first import, on next it will use cached one obviously Commented May 25, 2017 at 18:10

2 Answers 2

3

You don't need it in Python, you can use module imports as singletons and that's what most people do most of the time. Any module level code will be executed on import of the module.

But... DI sure is nice for large projects where different layers live in different python packages. I use the ZCA (Zope Component Architecture) as a DI system for all my large sqlalchemy projects and it's great. It is a bunch of extra boilerplate, so most small to medium projects don't bother, but it's really nice for large scale architecture, and awesome for having flexibility for testing, easy to mock out services and just have the DI system take care of swapping out your services.

Personally, I make a component that acts as my model engine with the session factory, and use zca lookup to get at it. I also register model classes as ZCA utilities and get at them through interface lookup, so that other reusable components can be implemented as zca adapters for the different model classes. A lot of the frameworks from the Zope world use it: Pyramid, Plone, Grok, BlueBream, Twisted.

I love DI, but YMMV, others hate the boilerplate!

Sign up to request clarification or add additional context in comments.

Comments

3
  • one needs a reference to the table to perform db operations like inserts, but one only gets a reference to the table after it is created!

    I don't see any problem here, in RDBMS you also should create table to perform other operations (like CRUD) with it.

    If you don't wanna create Table objects or mapping, you can always execute raw SQL statements.

  • That means the db connection, db operations and table declarations must be done in the same file

    Incorrect. We can refactor your example into separate modules like

    tables.py:

    from sqlalchemy import MetaData, Table, Column, Integer, String
    
    metadata = MetaData()
    users = Table('users', metadata,
                  Column('id', Integer, primary_key=True),
                  Column('name', String),
                  Column('fullname', String))
    

    main.py:

    from sqlalchemy import create_engine
    
    from tables import users
    
    db_uri = 'sqlite:///'
    engine = create_engine(db_uri)
    users.create(bind=engine)
    conn = engine.connect()
    values = {'name': 'John',
              'fullname': 'Doe'}
    ins = users.insert().values(values)
    result = conn.execute(ins)
    

    as we see tables declarations are in tables.py module, while working with connections/transactions is in main.py, am i missing something?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.