Imports and Flask 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:///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)

Defining the Class

import datetime
from datetime import datetime
import json


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




class Nutrition(db.Model):
    __tablename__ = ' nutritions'  # table name is plural, class name is singular

    # Define the User schema with "vars" from object
    id = db.Column(db.Integer, unique=True, primary_key=True)
    _username = db.Column(db.String(255), unique=False, nullable=False)
    _foodname = db.Column(db.String(255), unique=False, nullable=False)
    _calories = db.Column(db.String(255), unique=False, nullable=False)
    _fats = db.Column(db.String(255), unique=False, nullable=False)
    _carbs = db.Column(db.String(255), unique=False, nullable=False)


    # constructor of a User object, initializes the instance variables within object (self)
    def __init__(self, username, foodname, calories,fats, carbs):
        self._username = username
        self._foodname = foodname    # variables with self prefix become part of the object, 
        self._calories = calories
        self._fats = fats
        self._carbs = carbs

    # a name getter method, extracts name from object
    @property
    def username(self):
        return self._username
    # a setter function, allows name to be updated after initial object creation
    @username.setter
    def username(self, username):
        self._username = username
        
        
    @property
    def foodname(self):
        return self._foodname
    # a setter function, allows name to be updated after initial object creation
    @foodname.setter
    def foodname(self, foodname):
        self._foodname = foodname
        
    # a getter method, extracts link from object
    @property
    def calories(self):
        return self._calories
    # a setter function, allows link to be updated after initial object creation
    @calories.setter
    def recipelink(self, calories):
        self._calories = calories
        
    # a getter method, extracts link from object
    @property
    def fats(self):
        return self._fats
    # a setter function, allows link to be updated after initial object creation
    @fats.setter
    def recipetype(self, fats):
        self._fats = fats

    # a getter method, extracts link from object
    @property
    def carbs(self):
        return self._carbs
    # a setter function, allows link to be updated after initial object creation
    @carbs.setter
    def recipecuisine(self, carbs):
        self._carbs = carbs
        
    
    @property
    # 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,
            "username" : self.username,
            "foodname" : self.foodname,
            "calories" : self.calories,
            "fats" : self.fats,
            "carbs" : self.carbs,
        }
    # CRUD update: updates user name, password, phone
    # returns self
    def update(self, username="", foodname="", calories="", fats="", carbs=""):
        """only updates values with length"""
        if len(username) > 0:
            self.username = username
        if len(foodname) > 0:
            self.foodname = foodname
        if len(calories) > 0:
            self.calories = calories
        if len(fats) > 0:
            self.fats = fats
        if len(carbs) > 0:
            self.carbs = carbs
        db.session.commit()
        return self

    # CRUD delete: remove self
    # None
    def delete(self):
        db.session.delete(self)
        db.session.commit()
        return None

Creating the Database

"""Database Creation and Testing """


# Builds working data for testing
def initNutrition():
    with app.app_context():
        """Create database and tables"""
        db.create_all()
        """Tester data for table"""
        r1 = Nutrition(username = "Ananya", foodname='Apple', calories='94 cal', fats='0.31g', carbs='20.77 g')
        r2 = Nutrition(username = "Ethan", foodname='Flour', calories='455.00 kcal', fats=' 1.23 g', carbs='92.01 g')
        r3 = Nutrition(username = "Ava", foodname='Orange', calories=' 61.57 kcal', fats='0.16 g', carbs='12.25 g')
        r4 = Nutrition(username = "Alexa", foodname='Milk', calories='148.84 kcal', fats='7.93 g', carbs=' 11.71 g')
        r5 = Nutrition(username = "Haseeb", foodname='Egg', calories='61.49 kcal', fats='4.09 g', carbs=' 0.31 g')
        r6= Nutrition(username = "Rashi", foodname='grapes', calories='85 kcal', fats='5.09 g', carbs='0.23 g')
        r7 = Nutrition(username = "Aiza", foodname='bread', calories='100 kcal', fats='6.08 g', carbs=' 0.78 g')
        r8 = Nutrition(username = "Anshi", foodname='banana', calories='76 kcal', fats='6.98 g', carbs=' 2.34 g')
        r9 = Nutrition(username = "Mortensen", foodname='ramen', calories='115 kcal', fats='3.89 g', carbs=' 0.23 g')
        r10 = Nutrition(username = "Yeung", foodname='butter', calories='86.9 kcal', fats='2.35 g', carbs=' 24.7 g')

    
        nutritions = [r1, r2, r3, r4, r5,r6,r7,r8,r9,r10]

        """Builds sample user/note(s) data"""
        for nutrition in nutritions:
            try:
                nutrition.create()
            except IntegrityError:
                '''fails with bad or duplicate data'''
                db.session.remove()
                print(f"Records exist, duplicate email, or error: {nutrition.model}")


initNutrition()

CRUD

READ FUNCTION

def read():
    with app.app_context():
        table = Nutrition.query.all()
    json_ready = [username.read() for username in table] 
    return json_ready

read()
[{'id': 1,
  'username': 'Ananya',
  'foodname': 'Apple',
  'calories': '94 cal',
  'fats': '0.31g',
  'carbs': '20.77 g'},
 {'id': 2,
  'username': 'Ethan',
  'foodname': 'Flour',
  'calories': '455.00 kcal',
  'fats': ' 1.23 g',
  'carbs': '92.01 g'},
 {'id': 3,
  'username': 'Ava',
  'foodname': 'Orange',
  'calories': ' 61.57 kcal',
  'fats': '0.16 g',
  'carbs': '12.25 g'},
 {'id': 4,
  'username': 'Alexa',
  'foodname': 'Milk',
  'calories': '148.84 kcal',
  'fats': '7.93 g',
  'carbs': ' 11.71 g'},
 {'id': 5,
  'username': 'Haseeb',
  'foodname': 'Egg',
  'calories': '61.49 kcal',
  'fats': '4.09 g',
  'carbs': ' 0.31 g'},
 {'id': 6,
  'username': 'Rashi',
  'foodname': 'grapes',
  'calories': '85 kcal',
  'fats': '5.09 g',
  'carbs': '0.23 g'},
 {'id': 7,
  'username': 'Aiza',
  'foodname': 'bread',
  'calories': '100 kcal',
  'fats': '6.08 g',
  'carbs': ' 0.78 g'},
 {'id': 8,
  'username': 'Anshi',
  'foodname': 'banana',
  'calories': '76 kcal',
  'fats': '6.98 g',
  'carbs': ' 2.34 g'},
 {'id': 9,
  'username': 'Mortensen',
  'foodname': 'ramen',
  'calories': '115 kcal',
  'fats': '3.89 g',
  'carbs': ' 0.23 g'},
 {'id': 10,
  'username': 'Yeung',
  'foodname': 'butter',
  'calories': '86.9 kcal',
  'fats': '2.35 g',
  'carbs': ' 24.7 g'},
 {'id': 11,
  'username': 'newuser',
  'foodname': 'water',
  'calories': '0',
  'fats': '0g',
  'carbs': '0g'},
 {'id': 12,
  'username': 'Ananya',
  'foodname': 'Apple',
  'calories': '94 cal',
  'fats': '0.31g',
  'carbs': '20.77 g'},
 {'id': 13,
  'username': 'Ethan',
  'foodname': 'Flour',
  'calories': '455.00 kcal',
  'fats': ' 1.23 g',
  'carbs': '92.01 g'},
 {'id': 14,
  'username': 'Ava',
  'foodname': 'Orange',
  'calories': ' 61.57 kcal',
  'fats': '0.16 g',
  'carbs': '12.25 g'},
 {'id': 15,
  'username': 'Alexa',
  'foodname': 'Milk',
  'calories': '148.84 kcal',
  'fats': '7.93 g',
  'carbs': ' 11.71 g'},
 {'id': 16,
  'username': 'Haseeb',
  'foodname': 'Egg',
  'calories': '61.49 kcal',
  'fats': '4.09 g',
  'carbs': ' 0.31 g'},
 {'id': 17,
  'username': 'Rashi',
  'foodname': 'grapes',
  'calories': '85 kcal',
  'fats': '5.09 g',
  'carbs': '0.23 g'},
 {'id': 18,
  'username': 'Aiza',
  'foodname': 'bread',
  'calories': '100 kcal',
  'fats': '6.08 g',
  'carbs': ' 0.78 g'},
 {'id': 19,
  'username': 'Anshi',
  'foodname': 'banana',
  'calories': '76 kcal',
  'fats': '6.98 g',
  'carbs': ' 2.34 g'},
 {'id': 20,
  'username': 'Mortensen',
  'foodname': 'ramen',
  'calories': '115 kcal',
  'fats': '3.89 g',
  'carbs': ' 0.23 g'},
 {'id': 21,
  'username': 'Yeung',
  'foodname': 'butter',
  'calories': '86.9 kcal',
  'fats': '2.35 g',
  'carbs': ' 24.7 g'},
 {'id': 22,
  'username': 'aisha2617',
  'foodname': 'grapes',
  'calories': '12',
  'fats': '23',
  'carbs': '23'},
 {'id': 23,
  'username': 'Ananya',
  'foodname': 'Apple',
  'calories': '94 cal',
  'fats': '0.31g',
  'carbs': '20.77 g'},
 {'id': 24,
  'username': 'Ethan',
  'foodname': 'Flour',
  'calories': '455.00 kcal',
  'fats': ' 1.23 g',
  'carbs': '92.01 g'},
 {'id': 25,
  'username': 'Ava',
  'foodname': 'Orange',
  'calories': ' 61.57 kcal',
  'fats': '0.16 g',
  'carbs': '12.25 g'},
 {'id': 26,
  'username': 'Alexa',
  'foodname': 'Milk',
  'calories': '148.84 kcal',
  'fats': '7.93 g',
  'carbs': ' 11.71 g'},
 {'id': 27,
  'username': 'Haseeb',
  'foodname': 'Egg',
  'calories': '61.49 kcal',
  'fats': '4.09 g',
  'carbs': ' 0.31 g'},
 {'id': 28,
  'username': 'Rashi',
  'foodname': 'grapes',
  'calories': '85 kcal',
  'fats': '5.09 g',
  'carbs': '0.23 g'},
 {'id': 29,
  'username': 'Aiza',
  'foodname': 'bread',
  'calories': '100 kcal',
  'fats': '6.08 g',
  'carbs': ' 0.78 g'},
 {'id': 30,
  'username': 'Anshi',
  'foodname': 'banana',
  'calories': '76 kcal',
  'fats': '6.98 g',
  'carbs': ' 2.34 g'},
 {'id': 31,
  'username': 'Mortensen',
  'foodname': 'ramen',
  'calories': '115 kcal',
  'fats': '3.89 g',
  'carbs': ' 0.23 g'},
 {'id': 32,
  'username': 'Yeung',
  'foodname': 'butter',
  'calories': '86.9 kcal',
  'fats': '2.35 g',
  'carbs': ' 24.7 g'}]

CHECK CREDENTIALS

def find_by_username(username):
    with app.app_context():
        user = Nutrition.query.filter_by(_username=username).first()
    return user 

def check_credentials(username, foodname):
    user = find_by_username(username)
    if user == None:
        return False
    if (user.is_foodname(foodname)):
        return True
    return False

def find_by_foodname(foodname):
    with app.app_context():
        user = Nutrition.query.filter_by(_foodname=foodname).first()
    return user 

def check_credentials(foodname):
    user = find_by_foodname(foodname)
    if user == None:
        return False
        
find_by_foodname("Apple")
<Nutrition 1>

CREATE FUNCTION

def create():
    username = input("Please enter a username. EX: your name:")
    username = find_by_username(username)
    try:
        print("Username has been Found\n", user.read())
        return
    except:
        pass # keep going
    
    username = input("Enter a username:")
    foodname = input("Enter the food name")
    calories = input("Enter the number calories")
    fats = input("Enter the amount of fat in grams")
    carbs = input("Enter the amount of carbs in grams")

    # Initialize User object 
    user = Nutrition(username=username,
                foodname=foodname,
                calories=calories, 
                fats=fats,
                carbs=carbs
                )
           
    # write object to database
    with app.app_context():
        try:
            object = user.create()
            print("User has been created\n", object.read())
        except:  # if link already exists
            print("Someone has already entered this {name}")  
create()
User has been created
 {'id': 22, 'username': 'aisha2617', 'foodname': 'grapes', 'calories': '12', 'fats': '23', 'carbs': '23'}

UPDATE FUNCTION

def update():
    username = input("Enter a username: ")
    user = db.session.query(Nutrition).filter_by(username=username).first()

    if user is None:
        print(f"User '{username}' not found.")
        return

    update_username = input("Enter the updated username: ")
    update_foodname = input("Enter the updated food name: ")
    update_calories = input("Enter the updated number of calories: ")
    update_fats = input("Enter the updated amount of fat in grams: ")
    update_carbs = input("Enter the updated amount of carbs in grams: ")

    user.username = update_username
    user.foodname = update_foodname
    user.calories = update_calories
    user.fats = update_fats
    user.carbs = update_carbs

    try:
            db.session.commit()
            print(f"User '{username}' has been successfully updated with the following values: "
                  f"username='{update_username}', foodname='{update_foodname}', calories='{update_calories}', "
                  f"fats='{update_fats}', carbs='{update_carbs}'.")
    except:
        print(f"Could not update user '{username}'.")

    with app.app_context():
        table = Nutrition.query.all()
    json_ready = [user.update() for user in table]
    return json_ready


update()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb Cell 17 in <cell line: 35>()
     <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=30'>31</a>     json_ready = [user.update() for user in table]
     <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=31'>32</a>     return json_ready
---> <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=34'>35</a> update()

/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb Cell 17 in update()
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=0'>1</a> def update():
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=1'>2</a>     username = input("Enter a username: ")
----> <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=2'>3</a>     user = db.session.query(Nutrition).filter_by(username=username).first()
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=4'>5</a>     if user is None:
      <a href='vscode-notebook-cell://wsl%2Bubuntu/home/ananyag2617/vscode/ananyagaurav2617/_notebooks/2023-03-20-test.ipynb#X26sdnNjb2RlLXJlbW90ZQ%3D%3D?line=5'>6</a>         print(f"User '{username}' not found.")

File ~/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/scoping.py:1593, in scoped_session.query(self, *entities, **kwargs)
   1567 def query(
   1568     self, *entities: _ColumnsClauseArgument[Any], **kwargs: Any
   1569 ) -> Query[Any]:
   1570     r"""Return a new :class:`_query.Query` object corresponding to this
   1571     :class:`_orm.Session`.
   1572 
   (...)
   1590 
   1591     """  # noqa: E501
-> 1593     return self._proxied.query(*entities, **kwargs)

File ~/anaconda3/lib/python3.9/site-packages/sqlalchemy/orm/scoping.py:195, in scoped_session._proxied(self)
    193 @property
    194 def _proxied(self) -> _S:
--> 195     return self.registry()

File ~/anaconda3/lib/python3.9/site-packages/sqlalchemy/util/_collections.py:639, in ScopedRegistry.__call__(self)
    638 def __call__(self) -> _T:
--> 639     key = self.scopefunc()
    640     try:
    641         return self.registry[key]  # type: ignore[no-any-return]

File ~/anaconda3/lib/python3.9/site-packages/flask_sqlalchemy/session.py:102, in _app_ctx_id()
    100 def _app_ctx_id() -> int:
    101     """Get the id of the current Flask application context for the session scope."""
--> 102     return id(app_ctx._get_current_object())

File ~/anaconda3/lib/python3.9/site-packages/werkzeug/local.py:513, in LocalProxy.__init__.<locals>._get_current_object()
    511     obj = local.get()  # type: ignore[union-attr]
    512 except LookupError:
--> 513     raise RuntimeError(unbound_message) from None
    515 return get_name(obj)

RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.

DELETE FUNCTION

def delete():
    username = input("Please type the username you want to delete")
    with app.app_context():
        result = Nutrition.query.filter_by(_username=username).first()
        if result is None:
            print("Item not found")
        else:
            result.delete()
            print("Deleted username:", result._username)

delete()
Deleted username: Yeung