Python: Flask SQLAlchemy

(Last Updated On: )

If you are using SQLAlchemy then no doubt you’ve ran into some questions. Find below some more common usages.

Installation:

pip install flask-sqlalchemy && pip freeze > requirements.txt

Table Definition:
You will notice that we are creating a unique constraint, primary keys, foreign keys.

from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import BOOLEAN, BIT, DATE, JSON, DOUBLE_PRECISION, UUID
from sqlalchemy.sql.functions import current_timestamp
from sqlalchemy.schema import UniqueConstraint

class MyTable(db.Model):
    __tablename__ = 'mytable'
    __table_args__ =  (UniqueConstraint('column_name'),)
    
    primarykey_id = db.Column(db.Integer, primary_key=True, autoincrement="True")
    bit_column = db.Column(BIT)
    text_column = db.Column(db.Text)
    foreignkey_id = db.Column(db.Integer, db.ForeignKey('table.column'))
    foreignkey = relationship("table", foreign_keys=[foreignkey_id ])
    bool_column = db.Column(BOOLEAN)
    created_date = db.Column(db.DateTime, default=current_timestamp())
    guid_column = db.Column(UUID)
    bigint_column = db.Column(db.BigInteger)
    double_precision_column = db.Column(DOUBLE_PRECISION)
    json_column = db.Column(JSON)
    string_column = db.Column(db.String(200))
    
    def __init__(self, primarykey_id, bit_column):
        self.primarykey_id = primarykey_id
        self.bit_column = bit_column

    def __repr__(self):
        return '<MyTable primarykey_id %r Name %r bit_column %r>' % (self.primarykey_id, self.bit_column)

Database Connections:
The default connection is the “SQLALCHEMY_DATABASE_URI”. However you can attach to other DB by using the BINDS as demonstrated below.

SQLALCHEMY_DATABASE_URI = "postgresql://##USER##:##PASS##@##SERVER##/##DB##"

SQLALCHEMY_BINDS = {
	"NAME": "postgresql://##USER##:##PASS##@##SERVER##/##DB##",
}

b.session().execute("", params=dict(), bind=db.get_engine(app, 'NAME'))

Concatenation:

 from sqlalchemy.sql.expression import func

func.concat(Table.Column,'-',Table.Column2)

Case Statements:

 from sqlalchemy.sql.expression import case

case([(column1 == 'some_val', 1)], else_=0)

Ordering:
The example below does multiple columns but you can do just one if need be.

 order_by(Table.Column1.desc(), Table.Column2.asc())

Literals:
If you want to add NULL as a column output you must use literals. You could do this with a numerical data or string or whatever.

 from sqlalchemy import literal

literal(None).label('column_name')

Retrieving Records:

 .first()
.one()
.fetchone()

.all()
.fetchall()

Joins:

 join(Table2, and_(Table2.column_id==Table1.column_id))
outerjoin(Table2, and_(Table2.column_id==Table1.column_id))

Union:

 query1.union(query2)

Select Fields:
This just selects one column but you can comma separate it.

 .with_entities(Table.Column)

Where:
You don’t have to use and_ or or_. Use them as needed.

 from sqlalchemy.sql.expression import and_, or_

.filter(and_(Table.Column1, Table.Column2, or_(Table.Column3_, Table.Column4))))

Not:
Select data where value is not NULL

 Table.Column.isnot(None)

Coalesce:

 from sqlalchemy.sql.functions import  coalesce

coalesce(Table.Column, 'Unknown')

Sum:

 from sqlalchemy.sql.expression import func

func.sum(Table.Column)

Count:

 from sqlalchemy.sql.expression import func

func.count()
func.count('*')

Max:

 from sqlalchemy.sql.expression import func

func.max(Table.Column)

AVG:

 from sqlalchemy.sql.expression import func

func.avg(Table.Column)

Substring:

 from sqlalchemy.sql.expression import func

func.substring(Table.Column, REGEX)

Like:

 Table.Column.like("value")

Not Like:

 from sqlalchemy.sql.expression import not_

not_(Table.Column.like("value"))

Commit & Rollback:

 #commit
session.commit()

#rollback
session.rollback()

Inline SQL:

 .execute('SELECT * FROM SP(:param)', params=dict(param=1))

Cast:

 from sqlalchemy.sql.functions import Cast

Cast(Table.Column, BIT)

Array with Distinct:

 from sqlalchemy.sql.expression import distinct, func

func.array_agg(distinct(Table.Column)).label('column_name')