How to verify session and engine objects are able to connect - python

The lines below declare the engine and session objects.
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
URL = 'mysql://root:pass#12.34.56.78/mydb'
engine = create_engine(URL, echo=False)
session = scoped_session(sessionmaker())
session.remove()
session.configure(bind=engine, autoflush=False, expire_on_commit=False)
I would like to know how engine and session objects could be used to check if they are able to connect to the database with URL, database name and credentials provided.

Related

sessionmaker object has no attribute add

I am trying to insert data into postgresql server. While doing so, when I try to add the data into the SQLalchemy session, I am getting the error "sessionmaker object has no attribute add":
from sqlalchemy.orm import Session
def create_new_user(user: UserCreate, db: Session):
user=User(username= user.username,
email=user.email,
hashed_password= Hasher.get_password_hash(user.password),
is_active=True,
is_superuser=False
)
db.add(user)
db.commit()
db.refresh(user)
return user
You should create an object from Session as show in this example; which uses a context-manager.
Currently, I use the scoped_session pattern (suitable for most web apps). Here is how my session initialization looks like:
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
engine = create_engine("sqlite://")
Session = scoped_session(sessionmaker(bind=engine))
Session() # --> returns the same object in the same thread

Can flask_migrate be run with sqlAlchemy create_engine in a database init file?

If I have an init.py file which looks as such:
from sqlalchemy import create_engine
import os
from sqlalchemy.orm import sessionmaker, scoped_session
from testserver.database.models.Base import Base
from sqlalchemy.ext.declarative import declarative_base
from flask_migrate import Migrate
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
def set_db_connection():
connection_string = 'sqlite:///' + os.path.join(BASE_DIR, 'testserver.db')
return connection_string
engine = create_engine(set_db_connection(), connect_args={'check_same_thread': False})
Session = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# Set the custom base class
Base = declarative_base(cls=Base)
def init_app(app):
Base.metadata.create_all(engine)
Base.metadata.bind = engine
Session.configure(bind=engine)
app.session = scoped_session(Session)
# Export session for use in other classes
db_session = Session()
If I am to make an update to my existing models. Can I use the flask_migrate package to successfully run a migration? And if so how?
Author of Flask-Migrate here. Flask-Migrate needs Flask-SQLAlchemy or Alchemical (a still somewhat experimental package I built that uses the newer query functionality in SQLAlchemy 1.4).
If you use plain SQLAlchemy, then work with Alembic directly.

How to use dependency injection with simple functions in Fast API?

I have a simple function in Fast API app that gets called by a cron, something like this (note that this is not a get or post Fast API method but a simple function):
def read_user(user_id: int, db: Session = Depends(get_db)):
db_user = crud.get_user(db, user_id=user_id)
where get_db is:
from database import SessionLocal
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
And database.py is:
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "://url-to-db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
Since crud method takes db (object of SessionLocal yielded by get_db) as a param, how do I use it as a dependency injection with my function just like we use in GET or POST as shown in code read_user method above.

SQLAlchemy mock Session connection

Everywhere I need to query the database in my application I import the Session from this file.
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
db_name = 'analytics'
db_url = 'postgresql+psycopg2://**:**#localhost:5432/{0}'.format(db_name)
Engine = create_engine(db_url, echo=False)
SessionMaker = sessionmaker(bind=Engine, autoflush=False)
Session = scoped_session(SessionMaker)
Base = declarative_base()
I'm writing some unit tests and need to mock the Session object so that whenever it is imported in my app, it connects to the unittest database rather than the analytics database.
class FacebookTest(unittest.TestCase):
#classmethod
def setUpClass(self):
"""
create unittest database and insert Premier League 2015-2016 season
"""
con = connect(user='**', host='localhost', password='**', database='postgres')
con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cur = con.cursor()
cur.execute('DROP DATABASE IF EXISTS unittest')
cur.execute('CREATE DATABASE unittest')
cur.close()
con.close()
Engine = create_engine('postgresql+psycopg2://**:**#localhost:5432/unittest')
Base.metadata.create_all(Engine)
Session.connection = Engine.connect()
Set your mock database on a different port, for example 5433 and change the port depending on which DB you want to connect to.
You can do like this. Let's say you have a db.py where you initiate your sessions and import them all over. Modify it like this (ignore reference to configurator, that's my internal module):
import psycopg2
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import configurator
Base = declarative_base()
def connect():
cfg = configurator.Configurator("database")
return psycopg2.connect(
user=cfg.user, host=cfg.host, dbname=cfg.db, port=cfg.port, password=cfg.pwd
)
def connect_test():
conn_string = (
"host='localhost' user='postgres' password='yourPassword' port='5433'"
)
return psycopg2.connect(conn_string)
def Session(database='dev'):
if database == 'dev':
engine = create_engine("postgresql://", creator=connect)
elif database == 'test':
engine = create_engine("postgresql://", creator=connect_test)
Session = sessionmaker(bind=engine)
return Session()
UPDATE: Important correction - added brackets in return session(), sorry about that.
UPDATE2: Changed code after explicit testing.

Declarative SQLAlchemy CREATE SQLITE in memory tables

This is how I setup my database for an application (in Flask):
from sqlalchemy.engine import create_engine
from sqlalchemy.orm import scoped_session, create_session
from sqlalchemy.ext.declarative import declarative_base
engine = None
db_session = scoped_session(lambda: create_session(bind=engine,
autoflush=False, autocommit=False, expire_on_commit=True))
Base = declarative_base()
Base.query = db_session.query_property()
def init_engine(uri, **kwargs):
global engine
engine = create_engine(uri, **kwargs)
Base.metadata.create_all(bind=engine)
return engine
If I connect to a file database that has had tables created already, everything works fine, but using sqlite:///:memory: as a target database gives me:
OperationalError: (OperationalError) no such table: users u'DELETE FROM users' ()
when querying like so for ex.:
UsersTable.query.delete()
db_session.commit()
I am accessing this code from a unit test. What is the problem?
Thanks
Edit:
Working setup of the application:
app = Flask(__name__)
app.config.from_object(__name__)
app.secret_key = 'XXX'
# presenters
from presenters.users import users
# register modules (presenters)
app.register_module(users)
# initialize the database
init_engine(db)
The code you posted doesn't contain any table/class declaration. Are you sure that the declaration is done before init_engine() is called?

Categories