Lesson Notes:

  • .model inherits is a parameter of class user (this is referencing the code in the lesson)

  • When you want to set something, you can create it or update it.

  • Use debugging to take a closer look at the code and how it works

  • For the initial data code block, if you were to put a red dot next to u6 and one at initusers(), when you debug it, it would go straight to initusers because that is the first time it is called.

  • Object Relational Model query, you can have a user give you an input, there will then be a query filter, meaning it will look if the user id is the same as the input,

  • JSON is easier to read in most code languages

College Board Notes:

  • Programs are used in an iterative and interactive way when processing information to allow users to gain insight and knowledge about data

  • Programmers can use programs to filter and clean digital data, which is gaining insight and knowledge from data

  • Combining data sources, clustering data, and classifyin data are parts of the process of using programs to gain insight and knowledge from data

  • Insight and knowledge can be obtained from translating and transforming digitally representeed information

  • Patterns can emerge when data are transformed using programs

  • People can filter, sort, combine, transform, cluster, or even classify the data in the program and that can lead to more knowledge and insight.

  • Programs can be used to process data to acquire information

  • Tables, diagrams, text and other visual tools can be used to communicate insight and knowledge gained from data

  • Search tools are useful for efficiently finding information

  • Data filtering systems are important tools for finding information and recognizing patterns in data

  • Programs such as spreadsheets help efficiently organize and find trends in information

"""
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:///example.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)
""" 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
# -- 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 Info(db.Model):
    __tablename__ = 'info'  # table name is plural, class name is singular

    # Define the User schema with "vars" from object
    id = db.Column(db.Integer, primary_key=True)
    _email = db.Column(db.String(255), unique=False, nullable=False)
    _uid = db.Column(db.String(255), unique=True, nullable=False)
    _fname = db.Column(db.String(255), unique=True, nullable=False)
    _lname = db.Column(db.String(255), unique=False, nullable=False)
    _score = db.Column(db.String(255), unique=False, nullable=False)

    # constructor of a User object, initializes the instance variables within object (self)
    def __init__(self, fname, uid, lname, email, score):
        self._fname = fname
        self._uid = uid    # variables with self prefix become part of the object, 
        self._lname = lname
        self.email = email
        self._score = score

    # a name getter method, extracts name from object
    @property
    def fname(self):
        return self._fname
    
    # a setter function, allows name to be updated after initial object creation
    @fname.setter
    def fname(self, fname):
        self._fname = fname

    @property
    def uid(self):
        return self._uid
    
    # a setter function, allows name 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
    # a getter method, extracts email from object

    @property
    def lname(self):
        return self._lname
    
    # a setter function, allows name to be updated after initial object creation
    @lname.setter
    def lname(self, lname):
        self._lname = lname
    
    @property
    def email(self):
        return self._email
    
    # a setter function, allows name to be updated after initial object creation
    @email.setter
    def email(self, email):
        self._email = email
    
    # dob property is returned as string, to avoid unfriendly outcomes
    @property
    def score(self):
        return self._score
    
    # a setter function, allows name to be updated after initial object creation
    @score.setter
    def score(self, score):
        self._score = score
    
    # output content using str(object) in human readable form, uses getter
    # 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,
            "uid": self.uid,
            "fname": self.fname,
            "lname": self.lname,
            "email": self.email,
            "score": self.score,
        }
"""Database Creation and Testing """


# Builds working data for testing
def initInfo():
    with app.app_context():
        """Create database and tables"""
        db.create_all()
        """Tester data for table"""
        u1 = Info(fname='Srihita', uid='sri', lname='Kotturi', email='srihitak@gmail.com', score='10')
        u2 = Info(fname='Lalitha', uid='lallu', lname='Chittila', email='lalithac@gmail.com', score='11')
        u3 = Info(fname='Chandram', uid='ram', lname='Kotturi', email='chandramk@gmail.com', score='12')
        u4 = Info(fname='Sumedh', uid='sumi', lname='Kotturi', email='sumedhk@gmail.com', score='13')
        u5 = Info(fname='Sobha', uid='sailu', lname='Chittila', email='sobhac@gmail.com', score='14')
        u6 = Info(fname='Aneel', uid='aneel', lname='Maha', email='aneelm@gmail.com', score='15')


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

        """Builds sample user/note(s) data"""
        for info in infos:
            try:
                '''add user to table'''
                object = info.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 {info.uid}, or error.")
                
initInfo()
Records exist uid sri, or error.
Records exist uid lallu, or error.
Records exist uid ram, or error.
Records exist uid sumi, or error.
Records exist uid sailu, or error.
Records exist uid aneel, or error.