class LineIngredientAssociations(db.Model): __tablename__='line_ingredient_associations' id_ = db.Column(db.Integer, primary_key=True) # separate because ingredient could appear more than once in a line ingredient_id = db.Column(db.ForeignKey('ingredient.id')) recipeline_id = db.Column(db.ForeignKey('recipe_line.id')) relevant_tokens = db.Column(db.String(), nullable=False) color_index = db.Column(db.Integer, nullable=False, default=0) # the index of the color for the frontend ingredient = db.relationship("Ingredient", back_populates='recipe_lines') recipe_line = db.relationship("RecipeLine", back_populates='ingredients') # TODO: Create a validator to confirm that the ingredient is on the recipe line def __repr__(self): return f"<Association of {self.ingredient} with {self.recipe_line} at {self.relevant_tokens}>"
class Recipe(db.Model): __tablename__ = 'recipe' id_ = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) url = db.Column( db.String(200)) # url of where the recipe was gotten (if applicable) creator_id = db.Column( db.Integer, db.ForeignKey('user.id_') ) # the creator of the recipe (used for editing permissions) creator = db.relationship("User", back_populates="recipes") recipe_lines = db.relationship("RecipeLine", back_populates='recipe', cascade="all, delete-orphan") grocery_lists = db.relationship("GroceryList", secondary=recipe_list_associations, back_populates="recipes") ai_list = db.relationship("GroceryList", back_populates="additional_ingredients") def __hash__(self): return hash(self.id_) def __eq__(self, other): return self.id_ == other.id_ def __repr__(self): return f"<Recipe '{self.name}' id_: {self.id_}>"
class GroceryList(db.Model): __tablename__ = 'grocery_list' id_ = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) recipes = db.relationship("Recipe", secondary=recipe_list_associations, back_populates="grocery_lists") additional_ingredients_id = db.Column(db.Integer, db.ForeignKey("recipe.id_")) creator_id = db.Column(db.Integer, db.ForeignKey( "user.id_")) # the creator of the grocerylist. can add others to edit creator = db.relationship("User", back_populates="created_lists") editors = db.relationship( "User", # other users with permission to edit the grocery list secondary=user_list_associations, back_populates="editable_lists") additional_ingredients = db.relationship("Recipe", back_populates="ai_list", cascade="all, delete-orphan", single_parent=True) # clears the grocerylist (for PUT requests) without removing the "Additional Ingredients" recipe # CURRENTLY UNUSED def clear_grocerylist(self): print(self) additional_ingredients = Recipe.query \ .filter(Recipe.name == "Additional Ingredients", Recipe.grocery_lists.contains(self)).first() print(additional_ingredients) additional_ingredients.recipe_lines.clear() self.recipes.clear() self.recipes.append(additional_ingredients) db.session.commit() def create_additional_ingredients_recipe(self): additional_ingredients_recipe = Recipe(name="Additional Ingredients", creator_id=self.creator_id) self.additional_ingredients = additional_ingredients_recipe self.recipes.append(additional_ingredients_recipe) db.session.add(additional_ingredients_recipe) print(additional_ingredients_recipe) db.session.commit() def __repr__(self): return f"<GroceryList '{self.name}'>"
class RawLine(db.Model): # TODO: refactor so there are less 'id' labels id = db.Column(db.Integer, primary_key=True) # the primary key hex_id = db.Column(db.String(8), default=get_hex_id, nullable=False, unique=True) # hex identifier for requests full_text = db.Column(db.String(100), nullable=False) # the text of the line list_id = db.Column(db.Integer, db.ForeignKey('recipe_list.id')) # the id of the list for the line text_to_colors = db.Column(db.String) cleaned_lines = db.relationship('CleanedLine', secondary=line_assocs, backref=db.backref('raw_lines', lazy='dynamic')) def __repr__(self): return f"{self.full_text}"
class CompiledList(db.Model): id = db.Column(db.Integer, primary_key=True) # the primary key date_created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) name = db.Column(db.String(20), nullable=False, default="Unnamed List") # user created name, optional hex_name = db.Column(db.String(20), unique=True, nullable=False) # name for database #TODO use hex_id() function lines = db.relationship('CleanedLine', backref='list', lazy=True) # cleaned lines for the list recipes = db.relationship('RecipeList', backref='complist', lazy=True) # all recipes that are in the compiled list user_id = db.Column(db.ForeignKey('user.id'), nullable=False) # the id of the user who made the list def __repr__(self): return f"{self.name}"
class RecipeList(db.Model): id = db.Column(db.Integer, primary_key=True) # the primary key name = db.Column(db.String, nullable=False) # name for recipe (from url) hex_name = db.Column(db.String(20), unique=True, nullable=False) # name for database #TODO use hex_id() function hex_color = db.Column(db.String(6), nullable=False) # randomly generated color for use in lists image_file = db.Column(db.String(20), nullable=False, default='default.jpg') # image for list recipe_url = db.Column(db.String(200)) compiled_list = db.Column(db.ForeignKey('compiled_list.id')) # the id of the compiled list lines = db.relationship('RawLine', backref='rlist', lazy=True) # the lines of the list def __repr__(self): return f"{self.hex_name} -- {self.recipe_url}"
class CleanedLine(db.Model): id = db.Column(db.Integer, primary_key=True) # the primary key index_in_list = db.Column(db.Integer) # index in the grocery list (for requests) TODO: create this automatically hex_id = db.Column(db.String(8), default=get_hex_id, nullable=False, unique=True) # hex identifier for requests amount = db.Column(db.Float) # the amount of ingredient (optional) measurement = db.Column(db.String(20)) # the measurement of the amount (optional) ingredient = db.Column(db.String(100), nullable=False) # the ingredient (required) checked = db.Column(db.Boolean, default=False) # whether or not the item is checked off the list comp_list = db.Column(db.Integer, db.ForeignKey('compiled_list.id')) rawline_index = db.Column(db.Integer, nullable=False) # the index of which ingredient it is in the raw line ingredient_color = db.Column(db.String, nullable=False) # the class color of the ingredient of the line def __repr__(self): return f"{self.ingredient} in list {self.comp_list}"
class RecipeLine(db.Model): __tablename__ = 'recipe_line' id_ = db.Column(db.Integer, primary_key=True) text = db.Column(db.String, nullable=False) # the text of the line recipe_id = db.Column(db.Integer, db.ForeignKey('recipe.id_')) recipe = db.relationship("Recipe", back_populates="recipe_lines") ingredients = db.relationship("LineIngredientAssociations", back_populates="recipe_line") def __hash__(self): return hash(self.id_) def __eq__(self, other): return self.id_ == other.id_ def __repr__(self): print(self.recipe) print(self.text) return f"<RecipeLine in '{self.recipe}' -- '{self.text[0:20]}...' >"
from flask import current_app from grocerylistapp import db from passlib.apps import custom_app_context as pwd_context from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired) # association table between RecipeLine and Ingredient models (many-to-many relationship) # CURRENTLY UNUSED line_ingredient_associations = db.Table('line_ingredient_associations_UNUSED', db.Column('ingredient', db.Integer, db.ForeignKey('ingredient.id')), db.Column('recipe_line', db.Integer, db.ForeignKey('recipe_line.id')), db.Column('relevant_tokens', db.String) ) # association table between Recipe and GroceryList models (many-to-many relationship) recipe_list_associations = db.Table('recipe_list_associations', db.Column('id', db.Integer, primary_key=True), db.Column('recipe', db.Integer, db.ForeignKey('recipe.id')), db.Column('grocery_list', db.Integer, db.ForeignKey('grocery_list.id')) ) # association table between GroceryList and User models (many-to-many relationship) user_list_associations = db.Table('user_list_associations', db.Column('id', db.Integer, primary_key=True), db.Column('grocery_list', db.Integer, db.ForeignKey('grocery_list.id')), db.Column('user', db.Integer, db.ForeignKey('user.id')) )
class CompiledList(db.Model): id = db.Column(db.Integer, primary_key=True) # the primary key date_created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) name = db.Column(db.String(20), nullable=False, default="Unnamed List") # user created name, optional hex_name = db.Column(db.String(20), unique=True, nullable=False) # name for database #TODO use hex_id() function lines = db.relationship('CleanedLine', backref='list', lazy=True) # cleaned lines for the list recipes = db.relationship('RecipeList', backref='complist', lazy=True) # all recipes that are in the compiled list user_id = db.Column(db.ForeignKey('user.id'), nullable=False) # the id of the user who made the list def __repr__(self): return f"{self.name}" line_assocs = db.Table('line_assocs', db.Column('rawline_id', db.Integer, db.ForeignKey('raw_line.id')), db.Column('cleanedline_id', db.Integer, db.ForeignKey('cleaned_line.id')) ) class RawLine(db.Model): # TODO: refactor so there are less 'id' labels id = db.Column(db.Integer, primary_key=True) # the primary key hex_id = db.Column(db.String(8), default=get_hex_id, nullable=False, unique=True) # hex identifier for requests full_text = db.Column(db.String(100), nullable=False) # the text of the line list_id = db.Column(db.Integer, db.ForeignKey('recipe_list.id')) # the id of the list for the line text_to_colors = db.Column(db.String) cleaned_lines = db.relationship('CleanedLine', secondary=line_assocs, backref=db.backref('raw_lines', lazy='dynamic')) def __repr__(self): return f"{self.full_text}"