Database and SQLAlchemy

In this blog we will explore using programs with data, focused on Databases. We will use SQLite Database to learn more about using Programs with Data. Use Debugging through these examples to examine Objects created in Code.

  • College Board talks about ideas like

    • Program Usage. "iterative and interactive way when processing information"
    • Managing Data. "classifying data are part of the process in using programs", "data files in a Table"
    • Insight "insight and knowledge can be obtained from ... digitally represented information"
    • Filter systems. 'tools for finding information and recognizing patterns"
    • Application. "the preserve has two databases", "an employee wants to count the number of book"
  • PBL, Databases, Iterative/OOP

    • Iterative. Refers to a sequence of instructions or code being repeated until a specific end result is achieved
    • OOP. A computer programming model that organizes software design around data, or objects, rather than functions and logic
    • SQL. Structured Query Language, abbreviated as SQL, is a language used in programming, managing, and structuring data

Imports and Flask Objects

Defines and key object creations

  • Comment on where you have observed these working? Provide a defintion of purpose.
    1. Flask app object:The purpose includes implementing a WSGI application and acts as the central object. 2. SQLAlchemy db object: The purpose includes maintaining communication between Python programs and databases.
"""
These imports define the key objects
"""

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

"""
These object and definitions are used throughout the Jupyter Notebook.
"""

# Setup of key Flask object (app)
app = Flask(__name__)
# Setup SQLAlchemy object and properties for the database (db)
database = 'sqlite:///files/sqlite.db'  # path and filename of database
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = database
app.config['SECRET_KEY'] = 'SECRET_KEY'
db = SQLAlchemy()


# This belongs in place where it runs once per project
db.init_app(app)

Model Definition

Define columns, initialization, and CRUD methods for users table in sqlite.db

  • Comment on these items in the class, purpose and defintion.
    • class User
    • db.Model inheritance
    • init method
    • @property, @<column>.setter
    • create, read, update, delete methods
""" database dependencies to support sqlite examples """
import datetime
from datetime import datetime
import json

from sqlalchemy.exc import IntegrityError
from werkzeug.security import generate_password_hash, check_password_hash


''' Tutorial: https://www.sqlalchemy.org/library.html#tutorials, try to get into a Python shell and follow along '''

# Define the User class to manage actions in the 'users' table # tells us user wants to create 
# -- Object Relational Mapping (ORM) is the key concept of SQLAlchemy
# -- a.) db.Model is like an inner layer of the onion in ORM
# -- b.) User represents data we want to store, something that is built on db.Model
# -- c.) SQLAlchemy ORM is layer on top of SQLAlchemy Core, then SQLAlchemy engine, SQL
class User(db.Model): # how you set up sqlite table, this allows you to use these
    __tablename__ = 'users'  # table name is plural, class name is singular

    # Define the User schema with "vars" from object
    id = db.Column(db.Integer, primary_key=True)
    _name = db.Column(db.String(255), unique=False, nullable=False)
    _uid = db.Column(db.String(255), unique=True, nullable=False)
    _password = db.Column(db.String(255), unique=False, nullable=False)
    _dob = db.Column(db.Date)

    # constructor of a User object, initializes the instance variables within object (self)
    def __init__(self, name, uid, password="123qwerty", dob=datetime.today()): # sets up data
        self._name = name    # variables with self prefix become part of the object, 
        self._uid = uid
        self.set_password(password) # this finalizes the password
        if isinstance(dob, str):  # not a date type     
            dob = date=datetime.today()
        self._dob = dob

    # a name getter method, extracts name from object
    @property # each attribute has a property, getter method 
    def name(self):
        return self._name
    
    # a setter function, allows name to be updated after initial object creation
    @name.setter # updating, creating, changing, adding the value 
    def name(self, name):
        self._name = name
    
    # a getter method, extracts uid from object
    @property
    def uid(self):
        return self._uid
    
    # a setter function, allows uid to be updated after initial object creation
    @uid.setter
    def uid(self, uid):
        self._uid = uid
        
    # check if uid parameter matches user id in object, return boolean
    def is_uid(self, uid):
        return self._uid == uid
    
    @property
    def password(self):
        return self._password[0:10] + "..." # because of security only show 1st characters

    # update password, this is conventional method used for setter
    def set_password(self, password):
        """Create a hashed password."""
        self._password = generate_password_hash(password, method='sha256')

    # check password parameter against stored/encrypted password
    def is_password(self, password):
        """Check against hashed password."""
        result = check_password_hash(self._password, password)
        return result
    
    # dob property is returned as string, a string represents date outside object
    @property
    def dob(self):
        dob_string = self._dob.strftime('%m-%d-%Y')
        return dob_string
    
    # dob setter, verifies date type before it is set or default to today
    @dob.setter
    def dob(self, dob):
        if isinstance(dob, str):  # not a date type     
            dob = date=datetime.today()
        self._dob = dob
    
    # age is calculated field, age is returned according to date of birth
    @property
    def age(self):
        today = datetime.today()
        return today.year - self._dob.year - ((today.month, today.day) < (self._dob.month, self._dob.day))
    
    # output content using str(object) is in human readable form
    # output content using json dumps, this is ready for API response
    def __str__(self):
        return json.dumps(self.read())

    # CRUD create/add a new record to the table
    # returns self or None on error
    def create(self):
        try:
            # creates a person object from User(db.Model) class, passes initializers
            db.session.add(self)  # add prepares to persist person object to Users table
            db.session.commit()  # SqlAlchemy "unit of work pattern" requires a manual commit
            return self
        except IntegrityError:
            db.session.remove()
            return None

    # CRUD read converts self to dictionary
    # returns dictionary
    def read(self):
        return {
            "id": self.id, #class users
            "name": self.name,
            "uid": self.uid,
            "dob": self.dob,
            "age": self.age,
        }

    # CRUD update: updates user name, password, phone
    # returns self
    def update(self, name="", uid="", password=""):
        """only updates values with length"""
        if len(name) > 0:
            self.name = name
        if len(uid) > 0:
            self.uid = uid
        if len(password) > 0:
            self.set_password(password)
        db.session.commit()
        return self

    # CRUD delete: remove self
    # None
    def delete(self):
        db.session.delete(self) # performs update when id exists
        db.session.commit()
        return None
    

Initial Data

Uses SQLALchemy db.create_all() to initialize rows into sqlite.db

  • Comment on how these work?
    1. Create All Tables from db Object
    2. User Object Constructors
    3. Try / Except
"""Database Creation and Testing """


# Builds working data for testing
def initUsers():
    with app.app_context():
        """Create database and tables"""
        db.create_all()
        """Tester data for table"""
        u1 = User(name='Thomas Edison', uid='toby', password='123toby', dob=datetime(1847, 2, 11))
        u2 = User(name='Nikola Tesla', uid='niko', password='123niko')
        u3 = User(name='Alexander Graham Bell', uid='lex', password='123lex')
        u4 = User(name='Eli Whitney', uid='whit', password='123whit')
        u5 = User(name='Indiana Jones', uid='indi', dob=datetime(1920, 10, 21))
        u6 = User(name='Marion Ravenwood', uid='raven', dob=datetime(1921, 10, 21))


        users = [u1, u2, u3, u4, u5, u6]

        """Builds sample user/note(s) data"""
        for user in users:
            try:
                '''add user to table'''
                object = user.create()
                print(f"Created new uid {object.uid}")
            except:  # error raised if object nit created
                '''fails with bad or duplicate data'''
                print(f"Records exist uid {user.uid}, or error.")
                
initUsers()
---------------------------------------------------------------------------
OperationalError                          Traceback (most recent call last)
File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:145, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    144 try:
--> 145     self._dbapi_connection = engine.raw_connection()
    146 except dialect.loaded_dbapi.Error as err:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3275, in Engine.raw_connection(self)
   3254 """Return a "raw" DBAPI connection from the connection pool.
   3255 
   3256 The returned object is a proxied version of the DBAPI
   (...)
   3273 
   3274 """
-> 3275 return self.pool.connect()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:455, in Pool.connect(self)
    448 """Return a DBAPI connection from the pool.
    449 
    450 The connection is instrumented such that when its
   (...)
    453 
    454 """
--> 455 return _ConnectionFairy._checkout(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:1271, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy)
   1270 if not fairy:
-> 1271     fairy = _ConnectionRecord.checkout(pool)
   1273     if threadconns is not None:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:719, in _ConnectionRecord.checkout(cls, pool)
    718 else:
--> 719     rec = pool._do_get()
    721 try:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:169, in QueuePool._do_get(self)
    168 with util.safe_reraise():
--> 169     self._dec_overflow()
    170 raise

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:166, in QueuePool._do_get(self)
    165 try:
--> 166     return self._create_connection()
    167 except:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:396, in Pool._create_connection(self)
    394 """Called by subclasses to create a new ConnectionRecord."""
--> 396 return _ConnectionRecord(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:681, in _ConnectionRecord.__init__(self, pool, connect)
    680 if connect:
--> 681     self.__connect()
    682 self.finalize_callback = deque()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:906, in _ConnectionRecord.__connect(self)
    905     with util.safe_reraise():
--> 906         pool.logger.debug("Error on connect(): %s", e)
    907 else:
    908     # in SQLAlchemy 1.4 the first_connect event is not used by
    909     # the engine, so this will usually not be set

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:901, in _ConnectionRecord.__connect(self)
    900 self.starttime = time.time()
--> 901 self.dbapi_connection = connection = pool._invoke_creator(self)
    902 pool.logger.debug("Created new connection %r", connection)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/create.py:641, in create_engine.<locals>.connect(connection_record)
    639             return connection
--> 641 return dialect.connect(*cargs, **cparams)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/default.py:580, in DefaultDialect.connect(self, *cargs, **cparams)
    578 def connect(self, *cargs, **cparams):
    579     # inherits the docstring from interfaces.Dialect.connect
--> 580     return self.loaded_dbapi.connect(*cargs, **cparams)

OperationalError: unable to open database file

The above exception was the direct cause of the following exception:

OperationalError                          Traceback (most recent call last)
/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 8 in <cell line: 30>()
     <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=26'>27</a>                 '''fails with bad or duplicate data'''
     <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=27'>28</a>                 print(f"Records exist uid {user.uid}, or error.")
---> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=29'>30</a> initUsers()

/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 8 in initUsers()
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=5'>6</a> with app.app_context():
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=6'>7</a>     """Create database and tables"""
----> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=7'>8</a>     db.create_all()
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=8'>9</a>     """Tester data for table"""
     <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X10sZmlsZQ%3D%3D?line=9'>10</a>     u1 = User(name='Thomas Edison', uid='toby', password='123toby', dob=datetime(1847, 2, 11))

File ~/opt/anaconda3/lib/python3.9/site-packages/flask_sqlalchemy/extension.py:884, in SQLAlchemy.create_all(self, bind_key)
    867 def create_all(self, bind_key: str | None | list[str | None] = "__all__") -> None:
    868     """Create tables that do not exist in the database by calling
    869     ``metadata.create_all()`` for all or some bind keys. This does not
    870     update existing tables, use a migration library for that.
   (...)
    882         Added the ``bind`` and ``app`` parameters.
    883     """
--> 884     self._call_for_binds(bind_key, "create_all")

File ~/opt/anaconda3/lib/python3.9/site-packages/flask_sqlalchemy/extension.py:865, in SQLAlchemy._call_for_binds(self, bind_key, op_name)
    862     raise sa.exc.UnboundExecutionError(message) from None
    864 metadata = self.metadatas[key]
--> 865 getattr(metadata, op_name)(bind=engine)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/sql/schema.py:5581, in MetaData.create_all(self, bind, tables, checkfirst)
   5557 def create_all(
   5558     self,
   5559     bind: _CreateDropBind,
   5560     tables: Optional[_typing_Sequence[Table]] = None,
   5561     checkfirst: bool = True,
   5562 ) -> None:
   5563     """Create all tables stored in this metadata.
   5564 
   5565     Conditional by default, will not attempt to recreate tables already
   (...)
   5579 
   5580     """
-> 5581     bind._run_ddl_visitor(
   5582         ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables
   5583     )

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3225, in Engine._run_ddl_visitor(self, visitorcallable, element, **kwargs)
   3219 def _run_ddl_visitor(
   3220     self,
   3221     visitorcallable: Type[Union[SchemaGenerator, SchemaDropper]],
   3222     element: SchemaItem,
   3223     **kwargs: Any,
   3224 ) -> None:
-> 3225     with self.begin() as conn:
   3226         conn._run_ddl_visitor(visitorcallable, element, **kwargs)

File ~/opt/anaconda3/lib/python3.9/contextlib.py:119, in _GeneratorContextManager.__enter__(self)
    117 del self.args, self.kwds, self.func
    118 try:
--> 119     return next(self.gen)
    120 except StopIteration:
    121     raise RuntimeError("generator didn't yield") from None

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3215, in Engine.begin(self)
   3188 @contextlib.contextmanager
   3189 def begin(self) -> Iterator[Connection]:
   3190     """Return a context manager delivering a :class:`_engine.Connection`
   3191     with a :class:`.Transaction` established.
   3192 
   (...)
   3213 
   3214     """
-> 3215     with self.connect() as conn:
   3216         with conn.begin():
   3217             yield conn

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3251, in Engine.connect(self)
   3228 def connect(self) -> Connection:
   3229     """Return a new :class:`_engine.Connection` object.
   3230 
   3231     The :class:`_engine.Connection` acts as a Python context manager, so
   (...)
   3248 
   3249     """
-> 3251     return self._connection_cls(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:147, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    145         self._dbapi_connection = engine.raw_connection()
    146     except dialect.loaded_dbapi.Error as err:
--> 147         Connection._handle_dbapi_exception_noconnection(
    148             err, dialect, engine
    149         )
    150         raise
    151 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:2413, in Connection._handle_dbapi_exception_noconnection(cls, e, dialect, engine, is_disconnect, invalidate_pool_on_disconnect, is_pre_ping)
   2411 elif should_wrap:
   2412     assert sqlalchemy_exception is not None
-> 2413     raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
   2414 else:
   2415     assert exc_info[1] is not None

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:145, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    143 if connection is None:
    144     try:
--> 145         self._dbapi_connection = engine.raw_connection()
    146     except dialect.loaded_dbapi.Error as err:
    147         Connection._handle_dbapi_exception_noconnection(
    148             err, dialect, engine
    149         )

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3275, in Engine.raw_connection(self)
   3253 def raw_connection(self) -> PoolProxiedConnection:
   3254     """Return a "raw" DBAPI connection from the connection pool.
   3255 
   3256     The returned object is a proxied version of the DBAPI
   (...)
   3273 
   3274     """
-> 3275     return self.pool.connect()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:455, in Pool.connect(self)
    447 def connect(self) -> PoolProxiedConnection:
    448     """Return a DBAPI connection from the pool.
    449 
    450     The connection is instrumented such that when its
   (...)
    453 
    454     """
--> 455     return _ConnectionFairy._checkout(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:1271, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy)
   1262 @classmethod
   1263 def _checkout(
   1264     cls,
   (...)
   1267     fairy: Optional[_ConnectionFairy] = None,
   1268 ) -> _ConnectionFairy:
   1270     if not fairy:
-> 1271         fairy = _ConnectionRecord.checkout(pool)
   1273         if threadconns is not None:
   1274             threadconns.current = weakref.ref(fairy)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:719, in _ConnectionRecord.checkout(cls, pool)
    717     rec = cast(_ConnectionRecord, pool._do_get())
    718 else:
--> 719     rec = pool._do_get()
    721 try:
    722     dbapi_connection = rec.get_connection()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:169, in QueuePool._do_get(self)
    167     except:
    168         with util.safe_reraise():
--> 169             self._dec_overflow()
    170         raise
    171 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    145     assert exc_value is not None
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:
    149     self._exc_info = None  # remove potential circular references

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:166, in QueuePool._do_get(self)
    164 if self._inc_overflow():
    165     try:
--> 166         return self._create_connection()
    167     except:
    168         with util.safe_reraise():

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:396, in Pool._create_connection(self)
    393 def _create_connection(self) -> ConnectionPoolEntry:
    394     """Called by subclasses to create a new ConnectionRecord."""
--> 396     return _ConnectionRecord(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:681, in _ConnectionRecord.__init__(self, pool, connect)
    679 self.__pool = pool
    680 if connect:
--> 681     self.__connect()
    682 self.finalize_callback = deque()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:906, in _ConnectionRecord.__connect(self)
    904 except BaseException as e:
    905     with util.safe_reraise():
--> 906         pool.logger.debug("Error on connect(): %s", e)
    907 else:
    908     # in SQLAlchemy 1.4 the first_connect event is not used by
    909     # the engine, so this will usually not be set
    910     if pool.dispatch.first_connect:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    145     assert exc_value is not None
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:
    149     self._exc_info = None  # remove potential circular references

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:901, in _ConnectionRecord.__connect(self)
    899 try:
    900     self.starttime = time.time()
--> 901     self.dbapi_connection = connection = pool._invoke_creator(self)
    902     pool.logger.debug("Created new connection %r", connection)
    903     self.fresh = True

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/create.py:641, in create_engine.<locals>.connect(connection_record)
    638         if connection is not None:
    639             return connection
--> 641 return dialect.connect(*cargs, **cparams)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/default.py:580, in DefaultDialect.connect(self, *cargs, **cparams)
    578 def connect(self, *cargs, **cparams):
    579     # inherits the docstring from interfaces.Dialect.connect
--> 580     return self.loaded_dbapi.connect(*cargs, **cparams)

OperationalError: (sqlite3.OperationalError) unable to open database file
(Background on this error at: https://sqlalche.me/e/20/e3q8)

Check for given Credentials in users table in sqlite.db

Use of ORM Query object and custom methods to identify user to credentials uid and password

  • Comment on purpose of following
    1. User.query.filter_by
    2. user.password
def find_by_uid(uid):
    with app.app_context():
        user = User.query.filter_by(_uid=uid).first() # after you find it, check to see if it's there # checking the id with the query
    return user # returns user object

# Check credentials by finding user and verify password
def check_credentials(uid, password):
    # query email and return user record
    user = find_by_uid(uid)
    if user == None:
        return False
    if (user.is_password(password)): # if it returns because it found something, this is ran 
        return True
    return False
        
#check_credentials("indi", "123qwerty")

Create a new User in table in Sqlite.db

Uses SQLALchemy and custom user.create() method to add row.

  • Comment on purpose of following
    1. user.find_by_uid() and try/except
    2. user = User(...)
    3. user.dob and try/except
    4. user.create() and try/except
def create():
    # optimize user time to see if uid exists
    uid = input("Enter your user id:")
    user = find_by_uid(uid) # user types uid from the last cell to identify it in the data 
    try:
        print("Found\n", user.read())
        return
    except:
        pass # keep going
    
    # request value that ensure creating valid object
    name = input("Enter your name:")
    password = input("Enter your password")
    
    # Initialize User object before date
    user = User(name=name, 
                uid=uid, 
                password=password
                )
    
    # create user.dob, fail with today as dob
    dob = input("Enter your date of birth 'YYYY-MM-DD'")
    try:
        user.dob = datetime.strptime(dob, '%Y-%m-%d').date()
    except ValueError:
        user.dob = datetime.today()
        print(f"Invalid date {dob} require YYYY-mm-dd, date defaulted to {user.dob}")
           
    # write object to database
    with app.app_context():
        try:
            object = user.create()
            print("Created\n", object.read())
        except:  # error raised if object not created
            print("Unknown error uid {uid}")
        
create()
---------------------------------------------------------------------------
OperationalError                          Traceback (most recent call last)
File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:145, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    144 try:
--> 145     self._dbapi_connection = engine.raw_connection()
    146 except dialect.loaded_dbapi.Error as err:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3275, in Engine.raw_connection(self)
   3254 """Return a "raw" DBAPI connection from the connection pool.
   3255 
   3256 The returned object is a proxied version of the DBAPI
   (...)
   3273 
   3274 """
-> 3275 return self.pool.connect()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:455, in Pool.connect(self)
    448 """Return a DBAPI connection from the pool.
    449 
    450 The connection is instrumented such that when its
   (...)
    453 
    454 """
--> 455 return _ConnectionFairy._checkout(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:1271, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy)
   1270 if not fairy:
-> 1271     fairy = _ConnectionRecord.checkout(pool)
   1273     if threadconns is not None:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:719, in _ConnectionRecord.checkout(cls, pool)
    718 else:
--> 719     rec = pool._do_get()
    721 try:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:169, in QueuePool._do_get(self)
    168 with util.safe_reraise():
--> 169     self._dec_overflow()
    170 raise

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:166, in QueuePool._do_get(self)
    165 try:
--> 166     return self._create_connection()
    167 except:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:396, in Pool._create_connection(self)
    394 """Called by subclasses to create a new ConnectionRecord."""
--> 396 return _ConnectionRecord(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:681, in _ConnectionRecord.__init__(self, pool, connect)
    680 if connect:
--> 681     self.__connect()
    682 self.finalize_callback = deque()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:906, in _ConnectionRecord.__connect(self)
    905     with util.safe_reraise():
--> 906         pool.logger.debug("Error on connect(): %s", e)
    907 else:
    908     # in SQLAlchemy 1.4 the first_connect event is not used by
    909     # the engine, so this will usually not be set

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:901, in _ConnectionRecord.__connect(self)
    900 self.starttime = time.time()
--> 901 self.dbapi_connection = connection = pool._invoke_creator(self)
    902 pool.logger.debug("Created new connection %r", connection)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/create.py:641, in create_engine.<locals>.connect(connection_record)
    639             return connection
--> 641 return dialect.connect(*cargs, **cparams)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/default.py:580, in DefaultDialect.connect(self, *cargs, **cparams)
    578 def connect(self, *cargs, **cparams):
    579     # inherits the docstring from interfaces.Dialect.connect
--> 580     return self.loaded_dbapi.connect(*cargs, **cparams)

OperationalError: unable to open database file

The above exception was the direct cause of the following exception:

OperationalError                          Traceback (most recent call last)
/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 12 in <cell line: 38>()
     <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=34'>35</a>         except:  # error raised if object not created
     <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=35'>36</a>             print("Unknown error uid {uid}")
---> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=37'>38</a> create()

/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 12 in create()
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=1'>2</a> def create():
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=2'>3</a>     # optimize user time to see if uid exists
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=3'>4</a>     uid = input("Enter your user id:")
----> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=4'>5</a>     user = find_by_uid(uid) # user types uid from the last cell to identify it in the data 
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=5'>6</a>     try:
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=6'>7</a>         print("Found\n", user.read())

/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 12 in find_by_uid(uid)
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=1'>2</a> def find_by_uid(uid):
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=2'>3</a>     with app.app_context():
----> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=3'>4</a>         user = User.query.filter_by(_uid=uid).first() # after you find it, check to see if it's there # checking the id with the query
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X14sZmlsZQ%3D%3D?line=4'>5</a>     return user

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/query.py:2752, in Query.first(self)
   2750     return self._iter().first()  # type: ignore
   2751 else:
-> 2752     return self.limit(1)._iter().first()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/query.py:2855, in Query._iter(self)
   2852 params = self._params
   2854 statement = self._statement_20()
-> 2855 result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
   2856     statement,
   2857     params,
   2858     execution_options={"_sa_orm_load_options": self.load_options},
   2859 )
   2861 # legacy: automatically set scalars, unique
   2862 if result._attributes.get("is_single_entity", False):

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:2229, in Session.execute(self, statement, params, execution_options, bind_arguments, _parent_execute_state, _add_event)
   2168 def execute(
   2169     self,
   2170     statement: Executable,
   (...)
   2176     _add_event: Optional[Any] = None,
   2177 ) -> Result[Any]:
   2178     r"""Execute a SQL expression construct.
   2179 
   2180     Returns a :class:`_engine.Result` object representing
   (...)
   2227 
   2228     """
-> 2229     return self._execute_internal(
   2230         statement,
   2231         params,
   2232         execution_options=execution_options,
   2233         bind_arguments=bind_arguments,
   2234         _parent_execute_state=_parent_execute_state,
   2235         _add_event=_add_event,
   2236     )

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:2114, in Session._execute_internal(self, statement, params, execution_options, bind_arguments, _parent_execute_state, _add_event, _scalar_result)
   2100     (
   2101         statement,
   2102         execution_options,
   (...)
   2109         False,
   2110     )
   2112 bind = self.get_bind(**bind_arguments)
-> 2114 conn = self._connection_for_bind(bind)
   2116 if _scalar_result and not compile_state_cls:
   2117     if TYPE_CHECKING:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:1981, in Session._connection_for_bind(self, engine, execution_options, **kw)
   1979 if trans is None:
   1980     trans = self._autobegin_t()
-> 1981 return trans._connection_for_bind(engine, execution_options)

File <string>:2, in _connection_for_bind(self, bind, execution_options)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/state_changes.py:137, in _StateChange.declare_states.<locals>._go(fn, self, *arg, **kw)
    135 self._next_state = _StateChangeStates.CHANGE_IN_PROGRESS
    136 try:
--> 137     ret_value = fn(self, *arg, **kw)
    138 except:
    139     raise

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:1108, in SessionTransaction._connection_for_bind(self, bind, execution_options)
   1103             raise sa_exc.InvalidRequestError(
   1104                 "Session already has a Connection associated for the "
   1105                 "given Connection's Engine"
   1106             )
   1107     else:
-> 1108         conn = bind.connect()
   1109         local_connect = True
   1111 try:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3251, in Engine.connect(self)
   3228 def connect(self) -> Connection:
   3229     """Return a new :class:`_engine.Connection` object.
   3230 
   3231     The :class:`_engine.Connection` acts as a Python context manager, so
   (...)
   3248 
   3249     """
-> 3251     return self._connection_cls(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:147, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    145         self._dbapi_connection = engine.raw_connection()
    146     except dialect.loaded_dbapi.Error as err:
--> 147         Connection._handle_dbapi_exception_noconnection(
    148             err, dialect, engine
    149         )
    150         raise
    151 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:2413, in Connection._handle_dbapi_exception_noconnection(cls, e, dialect, engine, is_disconnect, invalidate_pool_on_disconnect, is_pre_ping)
   2411 elif should_wrap:
   2412     assert sqlalchemy_exception is not None
-> 2413     raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
   2414 else:
   2415     assert exc_info[1] is not None

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:145, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    143 if connection is None:
    144     try:
--> 145         self._dbapi_connection = engine.raw_connection()
    146     except dialect.loaded_dbapi.Error as err:
    147         Connection._handle_dbapi_exception_noconnection(
    148             err, dialect, engine
    149         )

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3275, in Engine.raw_connection(self)
   3253 def raw_connection(self) -> PoolProxiedConnection:
   3254     """Return a "raw" DBAPI connection from the connection pool.
   3255 
   3256     The returned object is a proxied version of the DBAPI
   (...)
   3273 
   3274     """
-> 3275     return self.pool.connect()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:455, in Pool.connect(self)
    447 def connect(self) -> PoolProxiedConnection:
    448     """Return a DBAPI connection from the pool.
    449 
    450     The connection is instrumented such that when its
   (...)
    453 
    454     """
--> 455     return _ConnectionFairy._checkout(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:1271, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy)
   1262 @classmethod
   1263 def _checkout(
   1264     cls,
   (...)
   1267     fairy: Optional[_ConnectionFairy] = None,
   1268 ) -> _ConnectionFairy:
   1270     if not fairy:
-> 1271         fairy = _ConnectionRecord.checkout(pool)
   1273         if threadconns is not None:
   1274             threadconns.current = weakref.ref(fairy)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:719, in _ConnectionRecord.checkout(cls, pool)
    717     rec = cast(_ConnectionRecord, pool._do_get())
    718 else:
--> 719     rec = pool._do_get()
    721 try:
    722     dbapi_connection = rec.get_connection()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:169, in QueuePool._do_get(self)
    167     except:
    168         with util.safe_reraise():
--> 169             self._dec_overflow()
    170         raise
    171 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    145     assert exc_value is not None
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:
    149     self._exc_info = None  # remove potential circular references

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:166, in QueuePool._do_get(self)
    164 if self._inc_overflow():
    165     try:
--> 166         return self._create_connection()
    167     except:
    168         with util.safe_reraise():

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:396, in Pool._create_connection(self)
    393 def _create_connection(self) -> ConnectionPoolEntry:
    394     """Called by subclasses to create a new ConnectionRecord."""
--> 396     return _ConnectionRecord(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:681, in _ConnectionRecord.__init__(self, pool, connect)
    679 self.__pool = pool
    680 if connect:
--> 681     self.__connect()
    682 self.finalize_callback = deque()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:906, in _ConnectionRecord.__connect(self)
    904 except BaseException as e:
    905     with util.safe_reraise():
--> 906         pool.logger.debug("Error on connect(): %s", e)
    907 else:
    908     # in SQLAlchemy 1.4 the first_connect event is not used by
    909     # the engine, so this will usually not be set
    910     if pool.dispatch.first_connect:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    145     assert exc_value is not None
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:
    149     self._exc_info = None  # remove potential circular references

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:901, in _ConnectionRecord.__connect(self)
    899 try:
    900     self.starttime = time.time()
--> 901     self.dbapi_connection = connection = pool._invoke_creator(self)
    902     pool.logger.debug("Created new connection %r", connection)
    903     self.fresh = True

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/create.py:641, in create_engine.<locals>.connect(connection_record)
    638         if connection is not None:
    639             return connection
--> 641 return dialect.connect(*cargs, **cparams)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/default.py:580, in DefaultDialect.connect(self, *cargs, **cparams)
    578 def connect(self, *cargs, **cparams):
    579     # inherits the docstring from interfaces.Dialect.connect
--> 580     return self.loaded_dbapi.connect(*cargs, **cparams)

OperationalError: (sqlite3.OperationalError) unable to open database file
(Background on this error at: https://sqlalche.me/e/20/e3q8)

Reading users table in sqlite.db

Uses SQLALchemy query.all method to read data

  • Comment on purpose of following
    1. User.query.all
    2. json_ready assignment, google List Comprehension
# SQLAlchemy extracts all users from database, turns each user into JSON
def read():
    with app.app_context():
        table = User.query.all()
    json_ready = [user.read() for user in table] # "List Comprehensions", for each user add user.read() to list
    return json_ready

read()
---------------------------------------------------------------------------
OperationalError                          Traceback (most recent call last)
File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:145, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    144 try:
--> 145     self._dbapi_connection = engine.raw_connection()
    146 except dialect.loaded_dbapi.Error as err:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3275, in Engine.raw_connection(self)
   3254 """Return a "raw" DBAPI connection from the connection pool.
   3255 
   3256 The returned object is a proxied version of the DBAPI
   (...)
   3273 
   3274 """
-> 3275 return self.pool.connect()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:455, in Pool.connect(self)
    448 """Return a DBAPI connection from the pool.
    449 
    450 The connection is instrumented such that when its
   (...)
    453 
    454 """
--> 455 return _ConnectionFairy._checkout(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:1271, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy)
   1270 if not fairy:
-> 1271     fairy = _ConnectionRecord.checkout(pool)
   1273     if threadconns is not None:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:719, in _ConnectionRecord.checkout(cls, pool)
    718 else:
--> 719     rec = pool._do_get()
    721 try:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:169, in QueuePool._do_get(self)
    168 with util.safe_reraise():
--> 169     self._dec_overflow()
    170 raise

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:166, in QueuePool._do_get(self)
    165 try:
--> 166     return self._create_connection()
    167 except:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:396, in Pool._create_connection(self)
    394 """Called by subclasses to create a new ConnectionRecord."""
--> 396 return _ConnectionRecord(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:681, in _ConnectionRecord.__init__(self, pool, connect)
    680 if connect:
--> 681     self.__connect()
    682 self.finalize_callback = deque()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:906, in _ConnectionRecord.__connect(self)
    905     with util.safe_reraise():
--> 906         pool.logger.debug("Error on connect(): %s", e)
    907 else:
    908     # in SQLAlchemy 1.4 the first_connect event is not used by
    909     # the engine, so this will usually not be set

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:901, in _ConnectionRecord.__connect(self)
    900 self.starttime = time.time()
--> 901 self.dbapi_connection = connection = pool._invoke_creator(self)
    902 pool.logger.debug("Created new connection %r", connection)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/create.py:641, in create_engine.<locals>.connect(connection_record)
    639             return connection
--> 641 return dialect.connect(*cargs, **cparams)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/default.py:580, in DefaultDialect.connect(self, *cargs, **cparams)
    578 def connect(self, *cargs, **cparams):
    579     # inherits the docstring from interfaces.Dialect.connect
--> 580     return self.loaded_dbapi.connect(*cargs, **cparams)

OperationalError: unable to open database file

The above exception was the direct cause of the following exception:

OperationalError                          Traceback (most recent call last)
/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 14 in <cell line: 8>()
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=4'>5</a>     json_ready = [user.read() for user in table] # "List Comprehensions", for each user add user.read() to list
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=5'>6</a>     return json_ready
----> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=7'>8</a> read()

/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb Cell 14 in read()
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=1'>2</a> def read():
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=2'>3</a>     with app.app_context():
----> <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=3'>4</a>         table = User.query.all()
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=4'>5</a>     json_ready = [user.read() for user in table] # "List Comprehensions", for each user add user.read() to list
      <a href='vscode-notebook-cell:/Users/amitha/vscode/repository_1/_notebooks/2023-03-13-AP-unit2-4a.ipynb#X16sZmlsZQ%3D%3D?line=5'>6</a>     return json_ready

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/query.py:2697, in Query.all(self)
   2675 def all(self) -> List[_T]:
   2676     """Return the results represented by this :class:`_query.Query`
   2677     as a list.
   2678 
   (...)
   2695         :meth:`_engine.Result.scalars` - v2 comparable method.
   2696     """
-> 2697     return self._iter().all()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/query.py:2855, in Query._iter(self)
   2852 params = self._params
   2854 statement = self._statement_20()
-> 2855 result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
   2856     statement,
   2857     params,
   2858     execution_options={"_sa_orm_load_options": self.load_options},
   2859 )
   2861 # legacy: automatically set scalars, unique
   2862 if result._attributes.get("is_single_entity", False):

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:2229, in Session.execute(self, statement, params, execution_options, bind_arguments, _parent_execute_state, _add_event)
   2168 def execute(
   2169     self,
   2170     statement: Executable,
   (...)
   2176     _add_event: Optional[Any] = None,
   2177 ) -> Result[Any]:
   2178     r"""Execute a SQL expression construct.
   2179 
   2180     Returns a :class:`_engine.Result` object representing
   (...)
   2227 
   2228     """
-> 2229     return self._execute_internal(
   2230         statement,
   2231         params,
   2232         execution_options=execution_options,
   2233         bind_arguments=bind_arguments,
   2234         _parent_execute_state=_parent_execute_state,
   2235         _add_event=_add_event,
   2236     )

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:2114, in Session._execute_internal(self, statement, params, execution_options, bind_arguments, _parent_execute_state, _add_event, _scalar_result)
   2100     (
   2101         statement,
   2102         execution_options,
   (...)
   2109         False,
   2110     )
   2112 bind = self.get_bind(**bind_arguments)
-> 2114 conn = self._connection_for_bind(bind)
   2116 if _scalar_result and not compile_state_cls:
   2117     if TYPE_CHECKING:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:1981, in Session._connection_for_bind(self, engine, execution_options, **kw)
   1979 if trans is None:
   1980     trans = self._autobegin_t()
-> 1981 return trans._connection_for_bind(engine, execution_options)

File <string>:2, in _connection_for_bind(self, bind, execution_options)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/state_changes.py:137, in _StateChange.declare_states.<locals>._go(fn, self, *arg, **kw)
    135 self._next_state = _StateChangeStates.CHANGE_IN_PROGRESS
    136 try:
--> 137     ret_value = fn(self, *arg, **kw)
    138 except:
    139     raise

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/session.py:1108, in SessionTransaction._connection_for_bind(self, bind, execution_options)
   1103             raise sa_exc.InvalidRequestError(
   1104                 "Session already has a Connection associated for the "
   1105                 "given Connection's Engine"
   1106             )
   1107     else:
-> 1108         conn = bind.connect()
   1109         local_connect = True
   1111 try:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3251, in Engine.connect(self)
   3228 def connect(self) -> Connection:
   3229     """Return a new :class:`_engine.Connection` object.
   3230 
   3231     The :class:`_engine.Connection` acts as a Python context manager, so
   (...)
   3248 
   3249     """
-> 3251     return self._connection_cls(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:147, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    145         self._dbapi_connection = engine.raw_connection()
    146     except dialect.loaded_dbapi.Error as err:
--> 147         Connection._handle_dbapi_exception_noconnection(
    148             err, dialect, engine
    149         )
    150         raise
    151 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:2413, in Connection._handle_dbapi_exception_noconnection(cls, e, dialect, engine, is_disconnect, invalidate_pool_on_disconnect, is_pre_ping)
   2411 elif should_wrap:
   2412     assert sqlalchemy_exception is not None
-> 2413     raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
   2414 else:
   2415     assert exc_info[1] is not None

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:145, in Connection.__init__(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)
    143 if connection is None:
    144     try:
--> 145         self._dbapi_connection = engine.raw_connection()
    146     except dialect.loaded_dbapi.Error as err:
    147         Connection._handle_dbapi_exception_noconnection(
    148             err, dialect, engine
    149         )

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/base.py:3275, in Engine.raw_connection(self)
   3253 def raw_connection(self) -> PoolProxiedConnection:
   3254     """Return a "raw" DBAPI connection from the connection pool.
   3255 
   3256     The returned object is a proxied version of the DBAPI
   (...)
   3273 
   3274     """
-> 3275     return self.pool.connect()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:455, in Pool.connect(self)
    447 def connect(self) -> PoolProxiedConnection:
    448     """Return a DBAPI connection from the pool.
    449 
    450     The connection is instrumented such that when its
   (...)
    453 
    454     """
--> 455     return _ConnectionFairy._checkout(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:1271, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy)
   1262 @classmethod
   1263 def _checkout(
   1264     cls,
   (...)
   1267     fairy: Optional[_ConnectionFairy] = None,
   1268 ) -> _ConnectionFairy:
   1270     if not fairy:
-> 1271         fairy = _ConnectionRecord.checkout(pool)
   1273         if threadconns is not None:
   1274             threadconns.current = weakref.ref(fairy)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:719, in _ConnectionRecord.checkout(cls, pool)
    717     rec = cast(_ConnectionRecord, pool._do_get())
    718 else:
--> 719     rec = pool._do_get()
    721 try:
    722     dbapi_connection = rec.get_connection()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:169, in QueuePool._do_get(self)
    167     except:
    168         with util.safe_reraise():
--> 169             self._dec_overflow()
    170         raise
    171 else:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    145     assert exc_value is not None
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:
    149     self._exc_info = None  # remove potential circular references

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/impl.py:166, in QueuePool._do_get(self)
    164 if self._inc_overflow():
    165     try:
--> 166         return self._create_connection()
    167     except:
    168         with util.safe_reraise():

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:396, in Pool._create_connection(self)
    393 def _create_connection(self) -> ConnectionPoolEntry:
    394     """Called by subclasses to create a new ConnectionRecord."""
--> 396     return _ConnectionRecord(self)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:681, in _ConnectionRecord.__init__(self, pool, connect)
    679 self.__pool = pool
    680 if connect:
--> 681     self.__connect()
    682 self.finalize_callback = deque()

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:906, in _ConnectionRecord.__connect(self)
    904 except BaseException as e:
    905     with util.safe_reraise():
--> 906         pool.logger.debug("Error on connect(): %s", e)
    907 else:
    908     # in SQLAlchemy 1.4 the first_connect event is not used by
    909     # the engine, so this will usually not be set
    910     if pool.dispatch.first_connect:

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py:147, in safe_reraise.__exit__(self, type_, value, traceback)
    145     assert exc_value is not None
    146     self._exc_info = None  # remove potential circular references
--> 147     raise exc_value.with_traceback(exc_tb)
    148 else:
    149     self._exc_info = None  # remove potential circular references

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/pool/base.py:901, in _ConnectionRecord.__connect(self)
    899 try:
    900     self.starttime = time.time()
--> 901     self.dbapi_connection = connection = pool._invoke_creator(self)
    902     pool.logger.debug("Created new connection %r", connection)
    903     self.fresh = True

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/create.py:641, in create_engine.<locals>.connect(connection_record)
    638         if connection is not None:
    639             return connection
--> 641 return dialect.connect(*cargs, **cparams)

File ~/opt/anaconda3/lib/python3.9/site-packages/sqlalchemy/engine/default.py:580, in DefaultDialect.connect(self, *cargs, **cparams)
    578 def connect(self, *cargs, **cparams):
    579     # inherits the docstring from interfaces.Dialect.connect
--> 580     return self.loaded_dbapi.connect(*cargs, **cparams)

OperationalError: (sqlite3.OperationalError) unable to open database file
(Background on this error at: https://sqlalche.me/e/20/e3q8)

Hacks

  • Add this Blog to you own Blogging site. In the Blog add notes and observations on each code cell.
  • Change blog to your own database.
  • Add additional CRUD
    • Add Update functionality to this blog.
    • Add Delete functionality to this blog.

Update

import sqlite3

def update():
    uid = input("Enter user id to update")
    password = input("Enter updated password")
    if len(password) < 2:
        message = "hacked"
        password = 'gothackednewpassword123'
    else:
        message = "successfully updated"

    # Connect to the database file
    conn = sqlite3.connect(database)

    # Create a cursor object to execute SQL commands
    cursor = conn.cursor()

    try:
        # Execute an SQL command to update data in a table
        cursor.execute("UPDATE users SET _password = ? WHERE _uid = ?", (password, uid))
        if cursor.rowcount == 0:
            # The uid was not found in the table
            print(f"No uid {uid} was not found in the table")
        else:
            print(f"The row with user id {uid} the password has been {message}")
            conn.commit()
    except sqlite3.Error as error:
        print("Error while executing the UPDATE:", error)
        
    
    # Close the cursor and connection objects
    cursor.close()
    conn.close()
    
update()

Delete

import sqlite3

def delete():
    uid = input("Enter user id to delete")

    # Connect to the database file
    conn = sqlite3.connect(database)

    # Create a cursor object to execute SQL commands
    cursor = conn.cursor()
    
    try:
        cursor.execute("DELETE FROM users WHERE _uid = ?", (uid,))
        if cursor.rowcount == 0:
            # The uid was not found in the table
            print(f"No uid {uid} was not found in the table")
        else:
            # The uid was found in the table and the row was deleted
            print(f"The row with uid {uid} was successfully deleted")
        conn.commit()
    except sqlite3.Error as error:
        print("Error while executing the DELETE:", error)
        
    # Close the cursor and connection objects
    cursor.close()
    conn.close()
    
delete()