From be44243136d710eec0345f8459a64da377bab357 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Sun, 29 Mar 2026 13:43:38 +0200 Subject: Re-format reveal.js slides and add templates --- reveal.js/sqlalchemy.html | 927 +++++++++++++++++++++++----------------------- 1 file changed, 465 insertions(+), 462 deletions(-) (limited to 'reveal.js/sqlalchemy.html') diff --git a/reveal.js/sqlalchemy.html b/reveal.js/sqlalchemy.html index a0d6617..5dfae21 100644 --- a/reveal.js/sqlalchemy.html +++ b/reveal.js/sqlalchemy.html @@ -1,477 +1,480 @@ - + -
- -Simeon Simeonov
-Simeon Simeonov
+ -SQLAlchemy is a Python library created by Mike Bayer to provide a high-level Pythonic interface to RDBMS such as PostgreSQL, SQLite, MySQL, Oracle, DB2.
-SQLAlchemy includes RDBMS-independent SQL expression language and an object-relational mapper (ORM).
-SQLAlchemy is a Python library created by Mike Bayer to provide a high-level Pythonic interface to RDBMS such as PostgreSQL, SQLite, MySQL, Oracle, DB2.
+SQLAlchemy includes RDBMS-independent SQL expression language and an object-relational mapper (ORM).
+free software - free as in "freedom" (MIT licensed)
portability - the programming interface is independent of the type of RDBMS and connector used
security - no more SQL injections
abstraction - no need to bother with complex JOINs
object-orientation - you work with objects instead of tables and rows
performance - exploits the likehood of reusing a particular query
flexibility - you can override almost anything
free software - free as in "freedom" (MIT licensed)
portability - the programming interface is independent of the type of RDBMS and connector used
security - no more SQL injections
abstraction - no need to bother with complex JOINs
object-orientation - you work with objects instead of tables and rows
performance - exploits the likehood of reusing a particular query
flexibility - you can override almost anything
SQLAlchemy consists of several components, including the ORM.
-
- SQLAlchemy gives us the choice between classical mapping and the newer declarative mapping
-
-
- # option 1: classical mapping
- # explicitly defining Table objects and mapping them to pure Python base classes
- from sqlalchemy import create_engine
-
- # engine = create_engine("postgresql+psycopg2://user:zipassword@localhost/mydb" , echo=True)
- # The string form of the URL is dialect+driver://user:password@host/dbname[?key=value..],
- # engine = create_engine("sqlite:///library.db", echo=True)
- engine = create_engine("sqlite:///:memory:", echo=True)
-
- from sqlalchemy import Column, MetaData, Table
- from sqlalchemy import DateTime, ForeignKey, Integer, Numeric, String
-
- metadata = MetaData()
-
- production_types_table = Table(
- "production_types",
- metadata,
- Column("production_type_id", Integer, primary_key=True),
- Column("code", String(3), nullable=False, unique=True),
- Column("description", String), # Column("name", String(128)) is possible
- )
-
- bidding_areas_table = Table(
- "bidding_areas",
- metadata,
- Column("bidding_area_id", Integer, primary_key=True),
- Column("code", String(3), nullable=False, unique=True),
- Column("name", String(32)),
- )
-
- production_plans_table = Table(
- "production_plans",
- metadata,
- Column("record_created_time", DateTime(timezone=False), primary_key=True),
- Column("start_time", DateTime(timezone=False), primary_key=True),
- Column("bidding_area_id", Integer, ForeignKey("bidding_areas.bidding_area_id"), primary_key=True),
- Column("production_type_id", Integer, ForeignKey("production_types.production_type_id"), primary_key=True),
- Column("value", Numeric, nullable=False),
- )
-
- metadata.create_all(engine) # creates the tables
-
-
-
-
- # option 1: classical mapping (continues)
- # Using the SQL expression language (low level interface)
- from sqlalchemy import text
-
- insert_stmt = bidding_areas_table.insert(bind=engine)
- type(insert_stmt)
- # Out: <class 'sqlalchemy.sql.dml.Insert'>
- print(insert_stmt)
- # Out: INSERT INTO bidding_areas (bidding_area_id, code, name) VALUES (?, ?, ?)
-
- compiled_stmt = insert_stmt.compile()
- print(compiled_stmt.params)
- # Out: {'bidding_area_id': None, 'code': None, 'name': None}
-
- insert_stmt.execute(bidding_area_id=1, code="NO1", name="Elspot NO1") # insert a single entry
- # ... or a list of entries
- insert_stmt.execute(
- [
- {"bidding_area_id": 2, "code": "NO2", "name": "Elspot NO2"},
- {"bidding_area_id": 3, "code": "NO3", "name": "Elspot NO3"},
- {"bidding_area_id": 4, "code": "NO4", "name": "Elspot NO4"},
- {"bidding_area_id": 5, "code": "NO5", "name": "Elspot NO5"},
- {"bidding_area_id": 6, "code": "NO6", "name": "Elspot NO6"},
- ]
- )
-
- metadata.bind = engine # no need to explicitly bind the engine from now on
- select_stmt = bidding_areas_table.select(bidding_areas_table.c.bidding_area_id==2)
- result = select_stmt.execute()
- result.fetchall()
- # Out: [(2, 'NO2', 'Elspot NO2')]
-
- del_stmt = bidding_areas_table.delete()
- del_stmt.execute(whereclause=text("name='Elspot NO6'"))
- del_stmt.execute() # delete NO6
-
-
-
-
- # option 1: classical mapping (continues)
- # Defining regular base classes and mapping them to the Table objects
- from sqlalchemy.orm import mapper
-
- class ProductionType:
- def __init__(self, code, description):
- self.code = code
- self.description = description
-
- def __str__(self):
- return self.code
-
-
- class BiddingArea:
- def __init__(self, code, name):
- self.code = code
- self.name = name
-
- def __str__(self):
- return self.code
-
- mapper(ProductionType, production_types_table)
- mapper(BiddingArea, bidding_areas_table)
-
-
-
-
- from sqlalchemy.orm import relationship
-
- class ProductionPlan:
- def __init__(self, record_created_time, start_time, production_type, bidding_area, value):
- self.record_created_time = record_created_time
- self.start_time = start_time
- self.production_type = production_type
- self.bidding_area = bidding_area
- self.value = value
-
- def __str__(self):
- return (
- f"{self.record_created_time} {self.start_time} "
- f"{self.production_type} {self.bidding_area} {self.value}"
- )
-
-
- mapper(
- ProductionPlan,
- production_plans_table,
- properties = {
- "production_type": relationship(ProductionType, backref="production_plans"),
- "bidding_area": relationship(BiddingArea, backref="production_plans"),
- },
- )
-
-
-
-
- # option 2: declarative mapping
- from sqlalchemy.ext.declarative import declarative_base
-
- Base = declarative_base()
-
- class ProductionType(Base):
- __tablename__ = "production_types"
-
- production_type_id = Column(Integer, primary_key=True)
- code = Column(String(3), nullable=False, unique=True)
- description = Column(String)
-
- def __init__(self, code, description):
- self.code = code
- self.description = description
-
- def __str__(self):
- return self.code
-
- class BiddingArea(Base):
- __tablename__ = "bidding_areas"
-
- bidding_area_id = Column(Integer, primary_key=True)
- code = Column(String(3), nullable=False, unique=True)
- name = Column(String(32))
-
- def __init__(self, code, name):
- self.code = code
- self.name = name
-
- def __str__(self):
- return self.code
-
-
-
-
- # option 2: declarative mapping (continues)
- from sqlalchemy.orm import relationship, backref
-
- class ProductionPlan(Base):
- __tablename__ = "production_plans"
-
- record_created_time = Column(DateTime(timezone=False), primary_key=True)
- start_time = Column(DateTime(timezone=False), primary_key=True)
- bidding_area_id = Column(Integer, ForeignKey("bidding_areas.bidding_area_id"), primary_key=True)
- production_type_id = Column(Integer, ForeignKey("production_types.production_type_id"), primary_key=True)
- value = Column(Numeric, nullable=False)
-
- # defining relationships.
- # the defined attributes will reference 'ProductionType' and 'BiddingArea' objects
- production_type = relationship(ProductionType, backref=backref("production_plans"))
- bidding_area = relationship(BiddingArea, backref=backref("production_plans"))
-
- def __init__(self, record_created_time, start_time, production_type, bidding_area, value):
- self.record_created_time = record_created_time
- self.start_time = start_time
- self.production_type = production_type # a 'ProductionType' object
- self.bidding_area = bidding_area # a 'BiddingArea' object
- self.value = value
-
- def __str__(self):
- return (
- f"{self.record_created_time} {self.start_time} "
- f"{self.production_type} {self.bidding_area} {self.value}"
- )
-
- Base.metadata.create_all(engine) # create tables
-
-
-
-
- # adding some data...
- import datetime
- import decimal
-
- from sqlalchemy.orm import sessionmaker
-
- Session = sessionmaker(bind=engine) # bound session
- session = Session()
-
- bidding_area1 = BiddingArea("NO1", "Elspot NO1")
- session.add(bidding_area1)
-
- session.add_all(
- [
- BiddingArea("NO2", "Elspot NO2"),
- BiddingArea("NO3", "Elspot NO3"),
- BiddingArea("NO4", "Elspot NO4"),
- BiddingArea("NO5", "Elspot NO5"),
- ]
- )
-
- production_type_B37 = ProductionType("B37", "Thermal unspecified")
- production_type_B30 = ProductionType("B30", "Wind unspecified")
-
- session.add_all(
- [
- ProductionType("B19", "Wind Onshore"),
- ProductionType("B10", "Hydro-electric pure pumped storage head installation"),
- ProductionType("B11", "Hydro Run-of-river head installation"),
- ProductionType("B12", "Hydro-electric storage head installation"),
- ProductionType("A04", "Generation"),
- production_type_B37,
- production_type_B30,
- ]
- )
-
-
-
-
- # adding some production plans...
-
- session.add(
- ProductionPlan(
- datetime.datetime.now(),
- datetime.datetime(2022, 11, 2, 1, 0),
- production_type_B37,
- bidding_area1,
- decimal.Decimal("80.5"),
- )
- )
-
- production_plan2 = ProductionPlan(
- datetime.datetime.now(),
- datetime.datetime(2022, 11, 2, 2, 0),
- production_type_B37,
- bidding_area1,
- decimal.Decimal("90.5"),
- )
-
- session.add(production_plan2)
-
- session.flush() # execute pending operations
- session.commit() # execute and commit pending operations
-
- production_plan2.value = decimal.Decimal("70.5")
- production_plan2 in session
- # Out: True
-
- session.commit()
-
-
-
-
- import pandas as pd
-
- session.query(ProductionPlan).order_by(ProductionPlan.start_time) # returns a Query instance
- session.query(ProductionPlan).order_by(ProductionPlan.start_time).all() # returns an object-list
-
- # return all production plans where start_time after 2022-09-01 00:00
- session.query(ProductionPlan).filter(ProductionPlan.start_time > datetime.datetime(2022, 9, 1, 0, 0)).all()
-
- # return production plans with value > 80
- query = session.query(ProductionPlan).filter(ProductionPlan.value > 80).order_by(ProductionPlan.start_time)
- query.count() # returns 1
- production_plan = query.first() # returns the first object (element)
- production_plan = query.one() # raises NoResultFound exception or MultipleResultsFound in case elements != 1
-
- # generate Pandas DataFrame from a query or entire table
- df = pd.read_sql_table("my_table", con=session.get_bind()) # or con=engine
- df = pd.read_sql_query(query.statement, engine)
-
- # return production plans with production type 'B37'
- session.query(ProductionPlan).filter(
- ProductionPlan.production_type_id == ProductionType.production_type_id
- ).filter(ProductionType.code == "B37").all()
- session.query(ProductionPlan).join(ProductionType).filter(ProductionType.code == "B37").all()
- session.query(ProductionPlan).filter(ProductionPlan.production_type == production_type_B37).all()
- session.query(
- ProductionPlan
- ).from_statement(
- text(
- "SELECT pp.* FROM production_plans pp, production_types pt "
- "WHERE pp.production_type_id = pt.production_type_id AND pt.code=:code"
- )
- ).params(code="B37").all()
-
-
- SQLAlchemy consists of several components, including the ORM.
+
+ SQLAlchemy gives us the choice between classical mapping and the newer declarative mapping
+
+
+ # option 1: classical mapping
+ # explicitly defining Table objects and mapping them to pure Python base classes
+ from sqlalchemy import create_engine
+
+ # engine = create_engine("postgresql+psycopg2://user:zipassword@localhost/mydb" , echo=True)
+ # The string form of the URL is dialect+driver://user:password@host/dbname[?key=value..],
+ # engine = create_engine("sqlite:///library.db", echo=True)
+ engine = create_engine("sqlite:///:memory:", echo=True)
+
+ from sqlalchemy import Column, MetaData, Table
+ from sqlalchemy import DateTime, ForeignKey, Integer, Numeric, String
+
+ metadata = MetaData()
+
+ production_types_table = Table(
+ "production_types",
+ metadata,
+ Column("production_type_id", Integer, primary_key=True),
+ Column("code", String(3), nullable=False, unique=True),
+ Column("description", String), # Column("name", String(128)) is possible
+ )
+
+ bidding_areas_table = Table(
+ "bidding_areas",
+ metadata,
+ Column("bidding_area_id", Integer, primary_key=True),
+ Column("code", String(3), nullable=False, unique=True),
+ Column("name", String(32)),
+ )
+
+ production_plans_table = Table(
+ "production_plans",
+ metadata,
+ Column("record_created_time", DateTime(timezone=False), primary_key=True),
+ Column("start_time", DateTime(timezone=False), primary_key=True),
+ Column("bidding_area_id", Integer, ForeignKey("bidding_areas.bidding_area_id"), primary_key=True),
+ Column("production_type_id", Integer, ForeignKey("production_types.production_type_id"), primary_key=True),
+ Column("value", Numeric, nullable=False),
+ )
+
+ metadata.create_all(engine) # creates the tables
+
+
+
+
+ # option 1: classical mapping (continues)
+ # Using the SQL expression language (low level interface)
+ from sqlalchemy import text
+
+ insert_stmt = bidding_areas_table.insert(bind=engine)
+ type(insert_stmt)
+ # Out: <class 'sqlalchemy.sql.dml.Insert'>
+ print(insert_stmt)
+ # Out: INSERT INTO bidding_areas (bidding_area_id, code, name) VALUES (?, ?, ?)
+
+ compiled_stmt = insert_stmt.compile()
+ print(compiled_stmt.params)
+ # Out: {'bidding_area_id': None, 'code': None, 'name': None}
+
+ insert_stmt.execute(bidding_area_id=1, code="NO1", name="Elspot NO1") # insert a single entry
+ # ... or a list of entries
+ insert_stmt.execute(
+ [
+ {"bidding_area_id": 2, "code": "NO2", "name": "Elspot NO2"},
+ {"bidding_area_id": 3, "code": "NO3", "name": "Elspot NO3"},
+ {"bidding_area_id": 4, "code": "NO4", "name": "Elspot NO4"},
+ {"bidding_area_id": 5, "code": "NO5", "name": "Elspot NO5"},
+ {"bidding_area_id": 6, "code": "NO6", "name": "Elspot NO6"},
+ ]
+ )
+
+ metadata.bind = engine # no need to explicitly bind the engine from now on
+ select_stmt = bidding_areas_table.select(bidding_areas_table.c.bidding_area_id==2)
+ result = select_stmt.execute()
+ result.fetchall()
+ # Out: [(2, 'NO2', 'Elspot NO2')]
+
+ del_stmt = bidding_areas_table.delete()
+ del_stmt.execute(whereclause=text("name='Elspot NO6'"))
+ del_stmt.execute() # delete NO6
+
+
+
+
+ # option 1: classical mapping (continues)
+ # Defining regular base classes and mapping them to the Table objects
+ from sqlalchemy.orm import mapper
+
+ class ProductionType:
+ def __init__(self, code, description):
+ self.code = code
+ self.description = description
+
+ def __str__(self):
+ return self.code
+
+
+ class BiddingArea:
+ def __init__(self, code, name):
+ self.code = code
+ self.name = name
+
+ def __str__(self):
+ return self.code
+
+ mapper(ProductionType, production_types_table)
+ mapper(BiddingArea, bidding_areas_table)
+
+
+
+
+ from sqlalchemy.orm import relationship
+
+ class ProductionPlan:
+ def __init__(self, record_created_time, start_time, production_type, bidding_area, value):
+ self.record_created_time = record_created_time
+ self.start_time = start_time
+ self.production_type = production_type
+ self.bidding_area = bidding_area
+ self.value = value
+
+ def __str__(self):
+ return (
+ f"{self.record_created_time} {self.start_time} "
+ f"{self.production_type} {self.bidding_area} {self.value}"
+ )
+
+
+ mapper(
+ ProductionPlan,
+ production_plans_table,
+ properties = {
+ "production_type": relationship(ProductionType, backref="production_plans"),
+ "bidding_area": relationship(BiddingArea, backref="production_plans"),
+ },
+ )
+
+
+
+
+ # option 2: declarative mapping
+ from sqlalchemy.ext.declarative import declarative_base
+
+ Base = declarative_base()
+
+ class ProductionType(Base):
+ __tablename__ = "production_types"
+
+ production_type_id = Column(Integer, primary_key=True)
+ code = Column(String(3), nullable=False, unique=True)
+ description = Column(String)
+
+ def __init__(self, code, description):
+ self.code = code
+ self.description = description
+
+ def __str__(self):
+ return self.code
+
+ class BiddingArea(Base):
+ __tablename__ = "bidding_areas"
+
+ bidding_area_id = Column(Integer, primary_key=True)
+ code = Column(String(3), nullable=False, unique=True)
+ name = Column(String(32))
+
+ def __init__(self, code, name):
+ self.code = code
+ self.name = name
+
+ def __str__(self):
+ return self.code
+
+
+
+
+ # option 2: declarative mapping (continues)
+ from sqlalchemy.orm import relationship, backref
+
+ class ProductionPlan(Base):
+ __tablename__ = "production_plans"
+
+ record_created_time = Column(DateTime(timezone=False), primary_key=True)
+ start_time = Column(DateTime(timezone=False), primary_key=True)
+ bidding_area_id = Column(Integer, ForeignKey("bidding_areas.bidding_area_id"), primary_key=True)
+ production_type_id = Column(Integer, ForeignKey("production_types.production_type_id"), primary_key=True)
+ value = Column(Numeric, nullable=False)
+
+ # defining relationships.
+ # the defined attributes will reference 'ProductionType' and 'BiddingArea' objects
+ production_type = relationship(ProductionType, backref=backref("production_plans"))
+ bidding_area = relationship(BiddingArea, backref=backref("production_plans"))
+
+ def __init__(self, record_created_time, start_time, production_type, bidding_area, value):
+ self.record_created_time = record_created_time
+ self.start_time = start_time
+ self.production_type = production_type # a 'ProductionType' object
+ self.bidding_area = bidding_area # a 'BiddingArea' object
+ self.value = value
+
+ def __str__(self):
+ return (
+ f"{self.record_created_time} {self.start_time} "
+ f"{self.production_type} {self.bidding_area} {self.value}"
+ )
+
+ Base.metadata.create_all(engine) # create tables
+
+
+
+
+ # adding some data...
+ import datetime
+ import decimal
+
+ from sqlalchemy.orm import sessionmaker
+
+ Session = sessionmaker(bind=engine) # bound session
+ session = Session()
+
+ bidding_area1 = BiddingArea("NO1", "Elspot NO1")
+ session.add(bidding_area1)
+
+ session.add_all(
+ [
+ BiddingArea("NO2", "Elspot NO2"),
+ BiddingArea("NO3", "Elspot NO3"),
+ BiddingArea("NO4", "Elspot NO4"),
+ BiddingArea("NO5", "Elspot NO5"),
+ ]
+ )
+
+ production_type_B37 = ProductionType("B37", "Thermal unspecified")
+ production_type_B30 = ProductionType("B30", "Wind unspecified")
+
+ session.add_all(
+ [
+ ProductionType("B19", "Wind Onshore"),
+ ProductionType("B10", "Hydro-electric pure pumped storage head installation"),
+ ProductionType("B11", "Hydro Run-of-river head installation"),
+ ProductionType("B12", "Hydro-electric storage head installation"),
+ ProductionType("A04", "Generation"),
+ production_type_B37,
+ production_type_B30,
+ ]
+ )
+
+
+
+
+ # adding some production plans...
+
+ session.add(
+ ProductionPlan(
+ datetime.datetime.now(),
+ datetime.datetime(2022, 11, 2, 1, 0),
+ production_type_B37,
+ bidding_area1,
+ decimal.Decimal("80.5"),
+ )
+ )
+
+ production_plan2 = ProductionPlan(
+ datetime.datetime.now(),
+ datetime.datetime(2022, 11, 2, 2, 0),
+ production_type_B37,
+ bidding_area1,
+ decimal.Decimal("90.5"),
+ )
+
+ session.add(production_plan2)
+
+ session.flush() # execute pending operations
+ session.commit() # execute and commit pending operations
+
+ production_plan2.value = decimal.Decimal("70.5")
+ production_plan2 in session
+ # Out: True
+
+ session.commit()
+
+
+
+
+ import pandas as pd
+
+ session.query(ProductionPlan).order_by(ProductionPlan.start_time) # returns a Query instance
+ session.query(ProductionPlan).order_by(ProductionPlan.start_time).all() # returns an object-list
+
+ # return all production plans where start_time after 2022-09-01 00:00
+ session.query(ProductionPlan).filter(ProductionPlan.start_time > datetime.datetime(2022, 9, 1, 0, 0)).all()
+
+ # return production plans with value > 80
+ query = session.query(ProductionPlan).filter(ProductionPlan.value > 80).order_by(ProductionPlan.start_time)
+ query.count() # returns 1
+ production_plan = query.first() # returns the first object (element)
+ production_plan = query.one() # raises NoResultFound exception or MultipleResultsFound in case elements != 1
+
+ # generate Pandas DataFrame from a query or entire table
+ df = pd.read_sql_table("my_table", con=session.get_bind()) # or con=engine
+ df = pd.read_sql_query(query.statement, engine)
+
+ # return production plans with production type 'B37'
+ session.query(ProductionPlan).filter(
+ ProductionPlan.production_type_id == ProductionType.production_type_id
+ ).filter(ProductionType.code == "B37").all()
+ session.query(ProductionPlan).join(ProductionType).filter(ProductionType.code == "B37").all()
+ session.query(ProductionPlan).filter(ProductionPlan.production_type == production_type_B37).all()
+ session.query(
+ ProductionPlan
+ ).from_statement(
+ text(
+ "SELECT pp.* FROM production_plans pp, production_types pt "
+ "WHERE pp.production_type_id = pt.production_type_id AND pt.code=:code"
+ )
+ ).params(code="B37").all()
+
+
+