class RecipeBox(database.Model): """ Class that represents a user's recipe box (liked recipes, stored in the database). The following attributes of a user are stored in this table: is_liked (type: boolean) user_id (type: int) recipe_id (type: int) All three values are required. """ __tablename__ = 'recipe_boxes' id = database.Column(database.Integer, primary_key=True) is_liked = database.Column(database.Boolean, nullable=False, default=True) recipe_url = database.Column(database.String, nullable=False) recipe_title = database.Column(database.String, nullable=False) user_id = database.Column( database.Integer, database.ForeignKey('users.id', ondelete='cascade')) __table_args__ = (database.UniqueConstraint('user_id', 'recipe_url'), ) def __init__(self, is_liked: bool, recipe_url: str, recipe_title: str, user_id: int): self.is_liked = is_liked self.recipe_url = recipe_url self.recipe_title = recipe_title self.user_id = user_id
class Person(database.Model): person_id = database.Column(database.Integer, primary_key=True, unique=True) name = database.Column(database.String) address = database.Column(database.String) birth_day = database.Column(database.DateTime)
class Stock(database.Model): """ Class that represents a purchased stock in a portfolio. The following attributes of a stock are stored in this table: * stock symbol (type: string) * number of shares (type: integer) * purchase price (type: integer) Note: Due to the limitation in the data types supported by SQLite, the purchase price is stored as an integer: $24.10 -> 2410 $100.00 -> 10000 $87.65 -> 8765 """ __tablename__ = 'stocks' id = database.Column(database.Integer, primary_key=True) stock_symbol = database.Column(database.String, nullable=False) number_of_shares = database.Column(database.Integer, nullable=False) purchase_price = database.Column(database.Integer, nullable=False) def __init__(self, stock_symbol: str, number_of_shares: str, purchase_price: str): self.stock_symbol = stock_symbol self.number_of_shares = int(number_of_shares) self.purchase_price = int(float(purchase_price) * 100) def __repr__(self): return ( f'{self.stock_symbol} - {self.number_of_shares} shares ' f'purchased at ${self.purchase_price / 100}')
class User(database.Model): __tablename__ = "users" id = database.Column(database.Integer, primary_key=True, autoincrement=True) username = database.Column(database.String(256), nullable=False) email = database.Column(database.String(256), nullable=False, unique=True) name = database.Column(database.String(256), nullable=False) surname = database.Column(database.String(256), nullable=False) password = database.Column(database.String(512), nullable=False) created_at = database.Column(database.DateTime, default=func.now()) def __init__(self, username, email, name, surname, password): self.username = username self.email = email self.name = name self.surname = surname self.password = generate_password_hash(password) def to_json(self): return { "id": self.id, "username": self.username, "email": self.email, "name": self.name, "surname": self.surname, "created_at": self.created_at }
class Stock(database.Model): "Class to represent purchased stock in portfolio" __tablename__ = 'stocks' id = database.Column(database.Integer, primary_key=True) stock_symbol = database.Column(database.String, nullable=False) number_of_shares = database.Column(database.Integer, nullable=False) purchase_price = database.Column(database.Integer, nullable=False) def __init__(self, stock_symbol: str, number_of_shares: str, purchase_price: str): self.stock_symbol = stock_symbol self.number_of_shares = int(number_of_shares) self.purchase_price = int(float(purchase_price) * 100) def __repr__(self): return f'{self.stock_symbol} - {self.number_of_shares} shares purchased at ${self.purchase_price / 100}'
class ProviderObject(database.Model): __tablename__ = "data_store" id = database.Column(database.Integer, primary_key=True, autoincrement=True) model_id = database.Column(database.Integer, nullable=False) data_path = database.Column(database.String(512), nullable=False) def __init__(self, model_id, data_path): self.model_id = model_id self.data_path = data_path def to_json(self): return { "id": self.id, "model_id": self.model_id, "data_path": self.data_path, "filename": os.path.basename(self.data_path) }
class User(database.Model): "Class to represent users on the site" __tablename__ = 'users' id = database.Column(database.Integer, primary_key=True) email = database.Column(database.String, unique=True) password_hashed = database.Column(database.String(60)) def __init__(self, email: str, password_plaintext: str): self.email = email self.password_hashed = bcrypt.generate_password_hash( password_plaintext, current_app.config.get('BCRYPT_LOG_ROUNDS')).decode('utf-8') def is_password_correct(self, password_plaintext: str): return bcrypt.check_password_hash(self.password_hashed, password_plaintext) def __repr__(self): return f'<User: {self.email}>'
class ModelState(database.Model): __tablename__ = "model_state" id = database.Column(database.Integer, primary_key=True, autoincrement=True) model_id = database.Column(database.Integer, nullable=False) test_accuracy = database.Column(database.Float, nullable=False) test_loss = database.Column(database.Float, nullable=False) last_test_time = database.Column(database.DateTime, nullable=False) test_duration = database.Column(database.DateTime, nullable=False) def __init__(self, model_id, test_accuracy, test_loss, last_test_time, test_duration): self.model_id = model_id self.test_accuracy = test_accuracy self.test_loss = test_loss self.last_test_time = last_test_time self.test_duration = test_duration def to_json(self): return { "id": self.id, "model_id": self.model_id, "test_acc": self.test_accuracy, "test_loss": self.test_loss, "last_test_time": self.last_test_time, "test_duration": self.test_duration }
class User(database.Model): __tablename__ = "users" id = database.Column(database.Integer, primary_key=True, autoincrement=True) username = database.Column(database.String(256), nullable=False) email = database.Column(database.String(256), nullable=False, unique=True) name = database.Column(database.String(256), nullable=False) surname = database.Column(database.String(256), nullable=False) password = database.Column(database.String(512), nullable=False) created_at = database.Column(database.DateTime, default=func.now()) def __init__(self, username, email, name, surname): self.username = username self.email = email self.name = name self.surname = surname def to_json(self): return { "id": self.id, "username": self.username, "email": self.email, "name": self.name, "surname": self.surname, "created_at": self.created_at } def encode_auth_token(self, user_id): try: current_app.logger.debug(f"TOKEN_EXP_DAYS: {current_app.config.get('TOKEN_EXP_DAYS')}") payload = { "exp": datetime.datetime.utcnow() + datetime.timedelta(days=current_app.config.get("TOKEN_EXP_DAYS")), # "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=current_app.config.get("TOKEN_EXP_DAYS")), "iat": datetime.datetime.utcnow(), "sub": user_id } token = jwt.encode(payload, current_app.config.get("SECRET_KEY")) current_app.logger.debug(f"TOKEN: {token}") return token except Exception as e: current_app.logger.error(e) return e def decode_auth_token(self, token): try: payload = jwt.decode(token, current_app.config.get("SECRET")) return payload["sub"] except jwt.ExpiredSignatureError: return "Signature expired." except jwt.InvalidSignatureError: return "Invalid token."
class ModelDefinition(database.Model): __tablename__ = "models" id = database.Column(database.Integer, primary_key=True, autoincrement=True) model_title = database.Column(database.String(256), nullable=False) path_to_model = database.Column(database.String(512)) # Contains the path to uploaded model config file path_to_custom_objects = database.Column(database.String(512)) deployed_by = database.Column(database.Integer, nullable=False) model_framework = database.Column(database.String(128), nullable=False) def __init__(self, model_title, path_to_model, path_to_custom_objects, deployed_by, model_framework): self.model_title = model_title self.path_to_model = path_to_model self.path_to_custom_objects = path_to_custom_objects self.deployed_by = deployed_by self.model_framework = model_framework def to_json(self): return { "id": self.id, "model_title": self.model_title, "path": self.path_to_model, "custom_objects_path": self.path_to_custom_objects, "filename": os.path.basename(self.path_to_model), "custom_objects_filename": os.path.basename(self.path_to_custom_objects), "deployed_by": self.deployed_by, "model_framework": self.model_framework }
class Meal(database.Model): """ Class that handles a user's meal planning. Users can add items from their saved recipe box to create meals. The following attributes of a meal are stored in this table: * meal_date: The date a user plans to have a meal (required) * meal_title: The (optional) title of the meal, assigned by the user (not required). * meal_notes: The (optional) notes about the meal, provided by the user (not required). * recipe_id: The Spoonacular recipe_id (Required). * recipe_title: The Spoonacular recipe_title (Required). * recipe_url: The source URL of the recipe (Required). * user_id: The user_id (Foreign key from User table; required). """ __tablename__ = 'meals' id = database.Column(database.Integer, primary_key=True) meal_date = database.Column(database.DateTime, nullable=False, default=datetime.now()) meal_title = database.Column(database.String(100), nullable=True) meal_notes = database.Column(database.String(1000), nullable=True) recipe_id = database.Column(database.Integer, nullable=False) recipe_title = database.Column(database.String, nullable=False) recipe_url = database.Column(database.String, nullable=False) user_id = database.Column(database.Integer, database.ForeignKey('users.id')) def __init__(self, meal_date: datetime, meal_title: str, meal_notes: str, recipe_id: int, recipe_title: str, recipe_url: str, user_id: int): self.meal_date = meal_date self.meal_title = meal_title self.meal_notes = meal_notes self.recipe_id = recipe_id self.recipe_title = recipe_title self.recipe_url = recipe_url self.user_id = user_id
class UserProfile(database.Model): """ Class that represents a user's profile information. The following attributes of a user are stored in this table: username (type: string) first_name (type: string) last_name (type: string) The username attribute is required; first_name and last_name are optional. """ __tablename__ = 'user_profiles' id = database.Column(database.Integer, primary_key=True) username = database.Column(database.String, nullable=False) first_name = database.Column(database.String, nullable=True) last_name = database.Column(database.String, nullable=True) user_id = database.Column(database.Integer, database.ForeignKey('users.id')) def __init__(self, username: str, first_name: str, last_name: str, user_id: int): self.username = username self.first_name = first_name self.last_name = last_name self.user_id = user_id def __repr__(self): """ Show info about user_profile. """ u = self return f"<UserProfile {u.username} {u.first_name} {u.last_name}"
class ModelState(database.Model): __tablename__ = "model_state" id = database.Column(database.Integer, primary_key=True, autoincrement=True) model_id = database.Column(database.Integer, nullable=False) test_accuracy = database.Column(database.Float, nullable=False) test_loss = database.Column(database.Float, nullable=False) last_test_time = database.Column(database.DateTime, nullable=False) test_duration = database.Column(database.Float, nullable=False) test_status = database.Column(database.String, nullable=False) test_device = database.Column(database.String, nullable=False) def __init__(self, model_id, test_accuracy, test_loss, last_test_time, test_duration, test_status, test_device): self.model_id = model_id self.test_accuracy = test_accuracy self.test_loss = test_loss self.last_test_time = last_test_time self.test_duration = test_duration self.test_status = test_status self.test_device = test_device def to_json(self): return { "id": self.id, "model_id": self.model_id, "test_acc": round(self.test_accuracy, 2), "test_loss": round(self.test_loss, 2), "last_test_time": self.last_test_time.strftime("%d/%m/%Y %H:%M"), "test_duration": round(self.test_duration, 2), "test_status": self.test_status, "test_device": self.test_device }
class User(database.Model): """ Class that handles user logins and authentication. The following attributes of a login are stored in this table: * user_id (as a foreign key. When a user successfully registers, the user_id is inserted into the logins table.) * email - the user's email * hashed password - hashed password (using Flask-Bcrypt) * A foreign key relationship with UserProfile, which joins data from the Users and UserProfiles tables * A foreign key relationship with Follow, which manages a self-referential follower/following relatitionship. """ __tablename__ = 'users' id = database.Column(database.Integer, primary_key=True) email = database.Column(database.String, unique=True, nullable=False) password_hashed = database.Column(database.String(264), nullable=False) registered_on = database.Column(database.DateTime, nullable=True) email_confirmation_sent_on = database.Column(database.DateTime, nullable=True) email_confirmed = database.Column(database.Boolean, default=False) email_confirmed_on = database.Column(database.DateTime, nullable=True) def __init__(self, email: str, password_plaintext: str): self.email = email self.password_hashed = self._generate_password_hash(password_plaintext) self.registered_on = datetime.now() self.email_confirmation_sent_on = datetime.now() self.email_confirmed = False self.email_confirmed_on = None user_profiles = database.relationship('UserProfile', backref='user', lazy='dynamic') user_recipes = database.relationship('RecipeBox', backref='user', lazy='dynamic') followed = database.relationship( 'User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=database.backref('followers', lazy='dynamic'), lazy='dynamic') user_meals = database.relationship("Meal", backref='user', lazy='dynamic') def is_password_correct(self, password_plaintext: str): return bcrypt.check_password_hash(self.password_hashed, password_plaintext) def set_password(self, password_plaintext: str): self.password_hashed = self._generate_password_hash(password_plaintext) def follow(self, user): if not self.is_following(user): self.followed.append(user) def unfollow(self, user): if self.is_following(user): self.followed.remove(user) def is_following(self, user): return self.followed.filter( followers.c.followed_id == user.id).count() > 0 @staticmethod def _generate_password_hash(password_plaintext): return bcrypt.generate_password_hash( password_plaintext, current_app.config.get('BCRYPT_LOG_ROUNDS')).decode('utf-8') def __repr__(self): return f'<User: {self.email} {self.password_hashed}>' @property def is_authenticated(self): """Return True if the user has been successfully registered.""" return True @property def is_active(self): """Always True, as all users are active.""" return True @property def is_anonymous(self): """Always False, as anonymous users aren't supported.""" return False def get_id(self): """Return the user ID as a unicode string (`str`).""" return str(self.id)
class Stock(database.Model): """ Class that represents a purchased stock in a portfolio The following attributes of a stock are stored in this table: stock symbol (type: string) number of shares (type: integer) purchase price (type: integer) purchase date (type: datetime) current price (type: integer) date when current price was retrieved from the Alpha Vantage API (type: datetime) position value = current price * number of shares (type: integer) Note: Due to a limitation in the data types supported by SQLite, the purchase price is stored as an integer: $24.10 -> 2410 $100.00 -> 10000 $87.65 -> 8765 """ __tablename__ = 'stocks' id = database.Column(database.Integer, primary_key=True) stock_symbol = database.Column(database.String, nullable=False) number_of_shares = database.Column(database.Integer, nullable=False) purchase_price = database.Column(database.Integer, nullable=False) user_id = database.Column(database.Integer, database.ForeignKey('users.id')) purchase_date = database.Column(database.DateTime) current_price = database.Column(database.Integer) current_price_date = database.Column(database.DateTime) position_value = database.Column(database.Integer) def __init__(self, stock_symbol: str, number_of_shares: str, purchase_price: str, user_id: int, purchase_date=None): self.stock_symbol = stock_symbol self.number_of_shares = int(number_of_shares) self.purchase_price = int(float(purchase_price) * 100) self.user_id = user_id self.purchase_date = purchase_date self.current_price = 0 self.current_price_date = None self.position_value = 0 def __repr__(self): return f'{self.stock_symbol} - {self.number_of_shares} shares purchased at ${self.purchase_price / 100}' def create_alpha_vantage_get_url_daily_compact(self): return 'https://www.alphavantage.co/query?function={}&symbol={}&outputsize={}&apikey={}'.format( 'TIME_SERIES_DAILY_ADJUSTED', self.stock_symbol, 'compact', current_app.config['ALPHA_VANTAGE_API_KEY']) def get_stock_data(self): if self.current_price_date is None or self.current_price_date.date( ) != datetime.now().date(): url = self.create_alpha_vantage_get_url_daily_compact() try: r = requests.get(url) except requests.exceptions.ConnectionError: current_app.logger.error( f'Error! Network problem preventing retrieving the stock data ({ self.stock_symbol })!' ) # Status code returned from Alpha Vantage needs to be 200 (OK) to process stock data if r.status_code != 200: current_app.logger.warning( f'Error! Received unexpected status code ({ r.status_code }) ' f'when retrieving stock data ({ self.stock_symbol })!') return daily_data = r.json() # The key of 'Time Series (Daily)' needs to be present in order to process the stock data # Typically, this key will not be present if the API rate limit has been exceeded. if 'Time Series (Daily)' not in daily_data: current_app.logger.warning( f'Could not find Time Series (Daily) key when retrieving ' f'the stock data ({ self.stock_symbol })!') return for element in daily_data['Time Series (Daily)']: current_price = float( daily_data['Time Series (Daily)'][element]['4. close']) self.current_price = int(float(current_price) * 100) self.current_price_date = datetime.now() self.position_value = self.current_price * self.number_of_shares break current_app.logger.debug( f'Retrieved current price {self.current_price / 100} ' f'for the stock data ({ self.stock_symbol })!') def get_stock_position_value(self) -> float: return float(self.position_value / 100) def create_alpha_vantage_get_url_weekly(self): return 'https://www.alphavantage.co/query?function={}&symbol={}&apikey={}'.format( 'TIME_SERIES_WEEKLY_ADJUSTED', self.stock_symbol, current_app.config['ALPHA_VANTAGE_API_KEY']) def get_weekly_stock_data(self): title = '' labels = [] values = [] url = self.create_alpha_vantage_get_url_weekly() try: r = requests.get(url) except requests.exceptions.ConnectionError: current_app.logger.info( f"Error! Network problem preventing retrieving the weekly stock data ({ self.stock_symbol })!" ) if r.status_code == 200: weekly_data = r.json() title = f'Weekly Prices ({self.stock_symbol})' # Determine the start date as either: # - If the start date is less than 12 weeks ago, then use the date from 12 weeks ago # - Otherwise, use the purchase date start_date = self.purchase_date if (datetime.now() - self.purchase_date) < timedelta(weeks=12): start_date = datetime.now() - timedelta(weeks=12) for element in weekly_data['Weekly Adjusted Time Series']: date = datetime.fromisoformat(element) if date.date() > start_date.date(): labels.append(date) values.append(weekly_data['Weekly Adjusted Time Series'] [element]['4. close']) # Reverse the elements as the data from Alpha Vantage is read in latest to oldest labels.reverse() values.reverse() else: current_app.logger.info( f"Error! Received unexpected status code ({ r.status_code }) when retrieving weekly stock data ({ self.stock_symbol })!" ) return title, labels, values
class User(database.Model): """ Class that represents a user of the application The following attributes of a user are stored in this table: * email - email address of the user * hashed password - hashed password (using Flask-Bcrypt) * registered_on - date & time that the user registered * email_confirmation_sent_on - date & time that the confirmation email * was sent * email_confirmed - flag indicating if the user's email address has * been confirmed * email_confirmed_on - date & time that the user's email address was * confirmed REMEMBER: Never store the plaintext password in a database! """ __tablename__ = 'users' id = database.Column(database.Integer, primary_key=True) email = database.Column(database.String, unique=True) password_hashed = database.Column(database.String(60)) registered_on = database.Column(database.DateTime) email_confirmation_sent_on = database.Column(database.DateTime) email_confirmed = database.Column(database.Boolean, default=False) email_confirmed_on = database.Column(database.DateTime) def __init__(self, email: str, password_plaintext: str): """Create a new User object This constructor assumes that an email is sent to the new user to confirm their email address at the same time that the user is registered. """ self.email = email self.password_hashed = self._generate_password_hash(password_plaintext) self.registered_on = datetime.now() self.email_confirmation_sent_on = datetime.now() self.email_confirmed = False self.email_confirmed_on = None def is_password_correct(self, password_plaintext: str): return bcrypt.check_password_hash(self.password_hashed, password_plaintext) def __repr__(self): return f'<User: {self.email}' @property def is_authenticated(self): """Return True if the user has been successfully registered.""" return True @property def is_active(self): """Always True, as all users are active.""" return True @property def is_anonymous(self): """Always False, as anonymous users aren't supported.""" return False def get_id(self): """Return the user ID as a unicode string (`str`).""" return str(self.id) def set_password(self, password_plaintext: str): self.password_hashed = self._generate_password_hash(password_plaintext) @staticmethod def _generate_password_hash(password_plaintext: str): return bcrypt.generate_password_hash( password_plaintext, current_app.config.get('BCRYPT_LOG_ROUNDS') ).decode('utf-8')
from project import database, bcrypt from flask import current_app from datetime import datetime followers = database.Table( 'followers', database.Column('follower_id', database.Integer, database.ForeignKey('users.id')), database.Column('followed_id', database.Integer, database.ForeignKey('users.id'))) class User(database.Model): """ Class that handles user logins and authentication. The following attributes of a login are stored in this table: * user_id (as a foreign key. When a user successfully registers, the user_id is inserted into the logins table.) * email - the user's email * hashed password - hashed password (using Flask-Bcrypt) * A foreign key relationship with UserProfile, which joins data from the Users and UserProfiles tables * A foreign key relationship with Follow, which manages a self-referential follower/following relatitionship. """ __tablename__ = 'users' id = database.Column(database.Integer, primary_key=True) email = database.Column(database.String, unique=True, nullable=False) password_hashed = database.Column(database.String(264), nullable=False)