Exemplo n.º 1
0
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_}>"
Exemplo n.º 2
0
class Ingredient(db.Model):
    __tablename__ = 'ingredient'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True)    # the actual name of the ingredient
    recipe_lines = db.relationship("LineIngredientAssociations",    # lines where this ingredient appears.
                                   back_populates='ingredient')


    # validator to ensure that an ingredient is in the proper form (all lower case, no dashes or other symbols)
    @db.validates('name')
    def validate_name(self, key, address):
        if not address.islower():
            raise ValueError("Ingredient must be in all lower case!")
        return address

    # equal function for comparing different instances of the same Ingredient
    def __eq__(self, other):
        return self.id == other.id and self.name == other.name

    # hash function to enable sets to eliminate duplicates
    def __hash__(self):
        return hash((self.id, self.name))

    def __repr__(self):
        return f"<Ingredient '{self.name}'>"
Exemplo n.º 3
0
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}"
Exemplo n.º 4
0
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}"
Exemplo n.º 5
0
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}>"
Exemplo n.º 6
0
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}"
Exemplo n.º 7
0
class User(db.Model):
    __tablename__ = 'user'
    id_ = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(100), nullable=False, unique=True)
    email_validated = db.Column(db.Boolean, nullable=False, default=False)
    hashed_password = db.Column(db.String(16), nullable=False)
    access_level = db.Column(db.Integer, nullable=False, default=0)
    recipes = db.relationship(
        "Recipe", back_populates="creator")  # the recipes created by this user
    created_lists = db.relationship(
        "GroceryList", back_populates="creator",
        cascade="all, delete-orphan")  # lists created by this user
    editable_lists = db.relationship("GroceryList",
                                     secondary=user_list_associations,
                                     back_populates="editors")

    # function to hash password
    def hash_password(self, password):
        self.hashed_password = pwd_context.encrypt(password)

    # function to verify password
    def verify_password(self, password):
        print(self.hashed_password)
        return pwd_context.verify(password, self.hashed_password)

    # generate a secure token for authentication
    def generate_auth_token(self, expiration=600):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration)
        return s.dumps({'id': self.id}).decode("utf-8")

    # verify a token
    @staticmethod
    def verify_auth_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except SignatureExpired:
            print("signature expired")
            return None  # valid token, expired
        except BadSignature:
            print("invalid token")
            return None  # invalid token

        user = User.query.get(data['id'])
        return user

    def __repr__(self):
        return f"<User {id} -- email:'{self.email}' access_level: {self.access_level}>"
Exemplo n.º 8
0
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}'>"
Exemplo n.º 9
0
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]}...' >"
Exemplo n.º 10
0
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}"
Exemplo n.º 11
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    email_validated = db.Column(db.Boolean, default=False)
    password = db.Column(db.String(60), nullable=False)
    temporary = db.Column(db.Boolean, default=False)  # determines if user account is temporary (for guest users)
    checklists = db.relationship('CompiledList', backref='user', lazy=True)  # the user's grocery lists

    def __repr__(self):
        return f"(User('{self.username}', '{self.email}'"

    def get_reset_token(self, expires_sec=1800):
        s = TimedSerializer(current_app.config['SECRET_KEY'], expires_sec)
        return s.dumps({'user_id': self.id}).decode('utf-8')

    # TODO: combine this with get_reset_token
    def get_validate_token(self):
        s = Serializer(current_app.config['SECRET_KEY'])
        return s.dumps({'user_id': self.id}).decode('utf-8')

    @staticmethod
    def verify_reset_token(token):
        s = TimedSerializer(current_app.config['SECRET_KEY'])
        try:
            user_id = s.loads(token)['user_id']
        except:
            return None

        return User.query.get(user_id)

    # TODO: combine this with verify_reset_token
    @staticmethod
    def verify_email_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            user_id = s.loads(token)['user_id']
        except:
            return None

        return User.query.get(user_id)
Exemplo n.º 12
0
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'))
                                  )

Exemplo n.º 13
0
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}"