Example #1
0
    def get(self, username=None):
        """
        Render the public recipe list for a user or all users.
        """
        show_owners = False
        if username:
            publicuser = UserPrefs.all().filter('name =', username).get()
            recipes = Recipe.all()\
                            .filter('owner =', publicuser)\
                            .order('-grade')
            def setowner(recipe):
                recipe.owner = publicuser
                return recipe
            recipes = map(setowner, recipes)
        else:
            publicuser = None
            recipes = Recipe.all().order('-grade')
            recipes = [r for r in recipes]
            show_owners = True

        self.render('recipes.html', {
            'publicuser': publicuser,
            'recipes': recipes,
            'show_owners': show_owners
        })
Example #2
0
    def get_recipes(self, request):
        """
        Get a list of recipes, optionally filtered by user name.
        """
        offset, limit = get_limits(request)

        if request.user_name:
            publicuser = UserPrefs.all().filter('name =', request.user_name).get()

            if not publicuser:
                raise endpoints.NotFoundException(USER_NOT_FOUND)

            query = Recipe.all()\
                            .filter('owner =', publicuser)
        else:
            query = Recipe.all()

        if request.order == apimessages.RecipeOrder.NAME:
            query = query.order('name')
        elif request.order == apimessages.RecipeOrder.CREATED:
            query = query.order('-created')
        elif request.order == apimessages.RecipeOrder.EDITED:
            query = query.order('-edited')
        elif request.order == apimessages.RecipeOrder.LIKES:
            query = query.order('-likes_count')

        recipes = query.fetch(limit, offset=offset)

        items = []
        for recipe in recipes:
            items.append(recipe_to_response(recipe))

        return apimessages.RecipeListResponse(**{
            'items': items
        })
Example #3
0
    def get(self, username):
        """
        Render a user page.
        """
        publicuser = UserPrefs.all().filter('name =', username).get()

        if not publicuser:
            self.abort(404)

        recipes = Recipe.all()\
                        .filter('owner =', publicuser)\
                        .order('name')\
                        .run(limit=25)

        actions = UserAction.all()\
                            .filter('owner =', publicuser)\
                            .order('-created')\
                            .fetch(15)

        object_ids = UserAction.gather_object_ids(actions)

        user_map = {
            publicuser.key().id(): publicuser
        }

        for user in UserPrefs.get_by_id(object_ids['users']):
            user_map[user.key().id()] = user

        recipes = [r for r in recipes]
        recipe_ids = [recipe.key().id() for recipe in recipes]
        object_ids['recipes'] = [id for id in object_ids['recipes'] if id not in recipe_ids]

        recipe_map = {}

        for recipe in recipes:
            recipe.owner = publicuser
            recipe_map[recipe.key().id()] = recipe

        for recipe in Recipe.get_by_id(object_ids['recipes']):
            recipe_map[recipe.key().id()] = recipe

        brew_map = {}

        for brew in Brew.get_by_id(object_ids['brews']):
            brew_map[brew.key().id()] = brew

        self.render('user.html', {
            'publicuser': publicuser,
            'recipes': recipes,
            'actions': actions,
            'user_map': user_map,
            'recipe_map': recipe_map,
            'brew_map': brew_map
        })
Example #4
0
    def test_parse_incomplete_ingredients(self):
        s = textwrap.dedent("""\
            2 cup
            3 tbsp rice""")

        result = Recipe.parse_ingredients(s)
        self.assertEqual(len(result), 1)
Example #5
0
    def process(self, username=None, recipe_slug=None, brew_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name =', username)\
                              .get()

        if not publicuser:
            return [None, None, None]

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug = ', recipe_slug)\
                       .get()

        if not recipe:
            return [publicuser, None, None]

        if brew_slug is not None:
            brew = Brew.all()\
                       .filter('owner =', publicuser)\
                       .filter('recipe =', recipe)\
                       .filter('slug =', brew_slug)\
                       .get()

            if not brew:
                return [publicuser, recipe, None]
        else:
            brew = Brew()
            brew.owner = self.user
            brew.recipe = recipe

        return [publicuser, recipe, brew]
Example #6
0
    def get(self, username, recipe_slug):
        publicuser = UserPrefs.all().filter('name = ', username).get()

        if publicuser:
            recipe = Recipe.all()\
                           .filter('owner =', publicuser)\
                           .filter('slug =', recipe_slug)\
                           .get()
        else:
            recipe = None

        width = 260
        try:
            width = int(self.request.get('width'))
        except: pass

        if publicuser and recipe:
            self.render('recipe-embed.html', {
                'publicuser': publicuser,
                'recipe': recipe,
                'width': width,
            })
        else:
            self.render('recipe-embed-404.html', {
                'publicuser': publicuser,
                'width': width,
            })
Example #7
0
def generate_usable_slug(recipe):
    """
    Generate a usable slug for a given recipe. This method will try to slugify
    the recipe name and then append an integer if needed, increasing this
    integer until no existing recipe would be overwritten.
    """
    slug = slugify(recipe.name)

    # Reuse existing slug if we can
    if recipe.slug and recipe.slug == slug:
        return recipe.slug

    append = 0
    while True:
        count = Recipe.all()\
                      .filter('owner =', recipe.owner)\
                      .filter('slug =', slug)\
                      .count()

        if not count:
            break

        append += 1
        slug = slugify(recipe.name) + str(append)

    return slug
Example #8
0
 def object(self):
     if self.type in [self.TYPE_USER_FOLLOWED]:
         return UserPrefs.get_by_id(self.object_id)
     elif self.type in [self.TYPE_RECIPE_CREATED,
                        self.TYPE_RECIPE_EDITED,
                        self.TYPE_RECIPE_CLONED,
                        self.TYPE_RECIPE_LIKED]:
         from models.recipe import Recipe
         return Recipe.get_by_id(self.object_id)
Example #9
0
def recent_recipes():
    page = request.args.get('page', default=1, type=int)
    limit = 8
    recipes, page_count, recipe_count = Recipe.load_recipes(g.current_user, page=page, limit=limit)
    return render_template('recipes.html', 
        recipes=recipes, 
        page_count=page_count, 
        page=page,
        current_query_params={})
Example #10
0
def recipe(recipe_id=None):
    if recipe_id:
        recipe = Recipe.load_recipe(long(recipe_id), g.current_user)
        if recipe:
            return render_template('recipe.html', recipe=recipe)
        else:
            abort(404)
    else:
        abort(404)
Example #11
0
def favorites():
    page = request.args.get('page', default=1, type=int)
    limit = 16
    recipes, page_count, recipe_count = Recipe.load_recipes(g.current_user, 
        page=page, 
        limit=limit,
        order_by='saved.saved_at DESC',
        join=['saved'])
    return render_template('recipes.html', 
        recipes=recipes, 
        page_count=page_count, 
        page=page,
        current_query_params={})
Example #12
0
    def test_parse_steps(self):
        s = textwrap.dedent("""\
            Do something
            Do something else
            You are done""")

        expected_result = [
            {'step': 'Do something'},
            {'step': 'Do something else'},
            {'step': 'You are done'}]

        result = Recipe.parse_steps(s)
        self.assertEqual(result, expected_result)
Example #13
0
    def test_parse_ingredients(self):
        s = textwrap.dedent("""\
            1 oz cardimom
            2 cup flour
            3 tbsp rice""")

        expected_result = [
            {'name': 'cardimom', 'unit': 'oz', 'quantity': '1'},
            {'name': 'flour', 'unit': 'cup', 'quantity': '2'},
            {'name': 'rice', 'unit': 'tbsp', 'quantity': '3'}]

        result = Recipe.parse_ingredients(s)
        self.assertEqual(result, expected_result)
Example #14
0
    def get(self, username, recipe_slug):
        publicuser = UserPrefs.all().filter('name = ', username).get()
        if not publicuser:
            self.abort(404)

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.abort(404)

        self.render_xml(recipe.beerxml)
Example #15
0
def highest_rated_recipes():
    page = request.args.get('page', default=1, type=int)
    limit = 8
    recipes, page_count, recipe_count = Recipe.load_recipes(g.current_user, 
        page=page, 
        limit=limit,
        order_by='avg_ratings.avg_rating DESC',
        join=['avg_ratings'],
        where=['avg_ratings.avg_rating IS NOT NULL', 'avg_ratings.avg_rating >=3'])
    return render_template('recipes.html', 
        recipes=recipes, 
        page_count=page_count, 
        page=page,
        current_query_params={})  
Example #16
0
    def top_interesting_recipes(self):
        """
        Get a list of the top recipes that are interesting for this user,
        meaning that either the recipes belong to this user or any user
        that she is following. The list is ranked by the number of likes
        that each recipe has.
        """
        from models.recipe import Recipe

        following = self.following_users.run(batch_size=100)

        return Recipe.all()\
                     .filter('owner IN', [self] + list(following))\
                     .order('-likes_count')\
                     .fetch(15)
Example #17
0
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({
                'status': 'error',
                'error': 'User not found'
            })
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({
                'status': 'error',
                'error': 'Recipe not found'
            })
            return

        new_recipe = Recipe(**{
            'owner': UserPrefs.get(),
            'cloned_from': recipe,
            'color': recipe.color,
            'ibu': recipe.ibu,
            'alcohol': recipe.alcohol,
            'name': recipe.name,
            'description': recipe.description,
            'type': recipe.type,
            'style': recipe.style,
            'batch_size': recipe.batch_size,
            'boil_size': recipe.boil_size,
            'bottling_temp': recipe.bottling_temp,
            'bottling_pressure': recipe.bottling_pressure,
            '_ingredients': recipe._ingredients
        })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()

        action = UserAction()
        action.owner = UserPrefs.get()
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({
            'status': 'ok',
            'redirect': new_recipe.url
        })
Example #18
0
    def delete(self, username=None, recipe_slug=None):
        """
        Handle recipe delete. This will remove a recipe and return success
        or failure.
        """
        user = self.user

        if not user:
            self.render_json({
                'status': 'error',
                'error': 'User not logged in'
            })

        recipe = Recipe.all()\
                       .filter('slug = ', recipe_slug)\
                       .filter('owner =', user)\
                       .get()

        if recipe:
            # Delete all actions pointing to this recipe
            actions = UserAction.all()\
                                .filter('type IN', [UserAction.TYPE_RECIPE_CREATED,
                                                    UserAction.TYPE_RECIPE_EDITED,
                                                    UserAction.TYPE_RECIPE_CLONED,
                                                    UserAction.TYPE_RECIPE_LIKED])\
                                .filter('object_id =', recipe.key().id())\
                                .fetch(1000)

            for action in actions:
                action.delete()

            # Delete the actual recipe itself
            recipe.delete()

            self.render_json({
                'status': 'ok',
                'redirect': '/users/%(username)s/recipes' % {
                    'username': user.name
                }
            })
        else:
            self.render_json({
                'status': 'error',
                'error': 'Unable to delete recipe'
            })
Example #19
0
    def get_recipe(self, request):
        """
        Get a recipe by user name and recipe slug.
        """
        publicuser = UserPrefs.all().filter('name =', request.user_name).get()

        if not publicuser:
            raise endpoints.NotFoundException(USER_NOT_FOUND)

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', request.slug)\
                       .get()

        if not recipe:
            raise endpoints.NotFoundException(RECIPE_NOT_FOUND)

        return recipe_to_response(recipe)
Example #20
0
    def get(self):
        """
        Render the index page. Currently this renders a 'Coming soon' landing
        page that will eventually be replaced with a proper home page.
        """
        # Try to get recipes list from memcache instead of datastore
        recipes_html = memcache.get('index-recipes')
        if not recipes_html or settings.DEBUG:
            # No such luck... query the data store
            recipes = Recipe.all()\
                            .order('-grade')\
                            .run(limit=15)
            recipes_html = self.render('index-recipes.html', {
                'recipes': recipes
            }, write_to_stream=False)
            memcache.set('index-recipes', recipes_html, self.CACHE_TIME)

        self.render('index.html', {
            'recipes_html': recipes_html
        })
Example #21
0
def search_results(query=''):
    page = request.args.get('page', default=1, type=int)
    limit = 8
    where_clause = "recipes.name ILIKE '%%%%%s%%%%'" % adapt(str(query.replace('+','%%'))).getquoted()[1:-1]

    start_time = timer()
    recipes, page_count, recipe_count = Recipe.load_recipes(g.current_user, 
        page=page, 
        limit=limit,
        where=[where_clause])
    end_time = timer()

    natural_search_string = ' '.join(query.split('+'))

    return render_template('recipes.html', 
        recipes=recipes, 
        page_count=page_count, 
        page=page,
        current_query_params={'query':query},
        search_string=natural_search_string,
        success="We found %i result%s for '%s' (%.4f seconds)" % (recipe_count, ('s' if recipe_count != 1 else ''), natural_search_string, end_time - start_time))    
Example #22
0
    def post(self):
        """
        Import a new recipe or list of recipes from BeerXML to the
        currently logged in user's account.
        """
        user = self.user
        recipesxml = self.request.POST['file'].value

        for recipe in Recipe.new_from_beerxml(recipesxml):
            recipe.owner = user
            recipe.slug = generate_usable_slug(recipe)
            recipe.update_cache();
            key = recipe.put()

            action = UserAction()
            action.owner = user
            action.object_id = key.id()
            action.type = action.TYPE_RECIPE_CREATED
            action.put()

        self.redirect('/users/' + user.name + '/recipes')
    def put(self, recipe_id):

        json_data = request.get_json()

        recipe = Recipe.get_by_id(recipe_id=recipe_id)

        if recipe is None:
            return {'message': 'Recipe not found'}, HTTPStatus.NOT_FOUND

        current_user = get_jwt_identity()

        if current_user != recipe.user_id:
            return {'message': 'Access is not allowed'}, HTTPStatus.FORBIDDEN

        recipe.name = json_data['name']
        recipe.description = json_data['description']
        recipe.num_of_servings = json_data['num_of_servings']
        recipe.cook_time = json_data['cook_time']
        recipe.directions = json_data['directions']

        recipe.save()

        return recipe.data(), HTTPStatus.OK
Example #24
0
    def get(self, username, page, per_page, visibility):
        user = User.get_by_username(username=username)

        user = User.get_by_username(username=username)

        if user is None:
            return {'message': 'User not found'}, HTTPStatus.NOT_FOUND

        current_user = get_jwt_identity()
        if current_user == user.id and visibility in ['all', 'private']:
            pass
        else:
            visibility = 'public'

        # gets the paginated recipes by a particular author
        # lets recipe_pagination_schema serialize the paginated object.
        paginated_recipes = Recipe.get_all_by_user(user_id=user.id,
                                                   page=page,
                                                   per_page=per_page,
                                                   visibility=visibility)

        return recipe_pagination_schema.dump(
            paginated_recipes).data, HTTPStatus.OK
Example #25
0
    def put(self, recipe_id):
        """
        Gets the cover image in request.files
        and verifies whether it exists and if the file
        extension is permitted
        """
        file = request.files.get('cover')
        if not file:
            return {'message': 'Not a valid image'}, HTTPStatus.BAD_REQUEST

        if not image_set.file_allowed(file, file.filename):
            return {'message': 'File type not allowed'}, HTTPStatus.BAD_REQUEST

        # Check whether user hs the right to modify the recipe
        recipe = Recipe.get_by_id(recipe_id=recipe_id)

        if recipe is None:
            return {'message': 'Recipe not found'}, HTTPStatus.NOT_FOUND
        current_user = get_jwt_identity()
        if current_user != recipe.user_id:
            return {'message': 'Access in not allowed'}, HTTPStatus.FORBIDDEN

        # If the user has the right to, we will go
        # ahead and modify the cover image of the recipe
        if recipe.cover_image:
            cover_path = image_set.path(folder='recipes',
                                        filename=recipe.cover_image)
            if os.path.exists(cover_path):
                os.remove(cover_path)

        # User the save_image function to save the uploaded image
        filename = save_image(image=file, folder='recipes')

        recipe.cover_image = filename
        recipe.save()
        clear_cache('/recipes')  # clears old cache data when updated
        return recipe_cover_schema.dump(recipe).data, HTTPStatus.OK
Example #26
0
def show_recipe_ingredient(cuisine_name, recipe_name):
    cuisine = Cuisine.get_or_none(name=cuisine_name)

    if cuisine:
        recipe = Recipe.get_or_none(name=recipe_name)
        if recipe:
            if recipe.cuisine_id == cuisine.id:
                ingredient = RecipeIngredient.select().where(
                    RecipeIngredient.recipe_id == recipe.id)
                results = []
                for i in ingredient:
                    ingredient_data = {"name": i.name, "quantity": i.quantity}
                    results.append(ingredient_data)
                return jsonify({"data": results})
            else:
                return jsonify({
                    "errors":
                    recipe_name + " is not found in " + cuisine_name +
                    " cuisine."
                })
        else:
            return jsonify({"errors": "Recipe not exists"})
    else:
        return jsonify({"errors": cuisine_name + " cusine is not exist"})
Example #27
0
    def put(self, recipe_id):
        json_data = request.get_json()

        # recipe = next((recipe for recipe in recipe_list if recipe.id == recipe_id), None)
        recipe = Recipe.get_by_id(recipe_id=recipe_id)

        if recipe is None:
            return {'message': 'recipe not found'}, HTTPStatus.NOT_FOUND

        # we will further check whether it matches the identity of the user ID in the JWT
        current_user = get_jwt_identity()

        if current_user != recipe.user_id:
            return {'message': 'Access is not allowed'}, HTTPStatus.FORBIDDEN

        recipe.name = json_data['name']
        recipe.description = json_data['description']
        recipe.num_of_servings = json_data['num_of_servings']
        recipe.cook_time = json_data['cook_time']
        recipe.directions = json_data['directions']

        recipe.save()

        return recipe.data, HTTPStatus.OK
Example #28
0
def _populate_recipes(db_engine):
    session_maker = sessionmaker(bind=db_engine)
    session = session_maker()
    session.query(Recipe).delete()
    session.query(RecipeIngredient).delete()

    # Basic Pickaxe
    basic_pickaxe = Recipe(id=1, name='Basic Pickaxe')
    session.add(basic_pickaxe)
    session.query(Recipe).delete()
    stone_item = session.query(Item).filter(Item.name == 'stone').first()
    stick_item = session.query(Item).filter(Item.name == 'stick').first()

    basic_pickaxe_ingredient_1 = RecipeIngredient(recipe_id=basic_pickaxe.id,
                                                  item=stone_item,
                                                  item_amount=7)
    session.add(basic_pickaxe_ingredient_1)
    basic_pickaxe_ingredient_2 = RecipeIngredient(recipe_id=basic_pickaxe.id,
                                                  item=stick_item,
                                                  item_amount=4)
    session.add(basic_pickaxe_ingredient_2)

    session.commit()
    return
    def __init__(self, data: List[dict]) -> None:
        """
        Initializes a RecipeDatabase instance.

        :param data: list of recipes to store
        """
        super().__init__()

        # parse the dates to store them as datetime objects
        for recipe in data:
            recipe.update({
                'created_at': parse(recipe['created_at']),
                'updated_at': parse(recipe['updated_at']),
            })

        recipes = [Recipe(**recipe_data) for recipe_data in data]

        # provides a constant reading & updating time
        self._recipes_by_id = {recipe.id: recipe for recipe in recipes}

        # allows an easy filtering on recipes by cuisine
        self._recipes_by_cuisine = defaultdict(list)
        for recipe in recipes:
            self._recipes_by_cuisine[recipe.recipe_cuisine].append(recipe)
Example #30
0
    def put(self, recipe_id):
        file = request.files.get('cover_image')
        if not file:
            return {'message': 'Not a valid image'}, HTTPStatus.BAD_REQUEST
        if not image_set.file_allowed(file, file.filename):
            return {
                'message': 'File type not supported'
            }, HTTPStatus.BAD_REQUEST
        recipe = Recipe.get_by_id(recipe_id)
        if recipe is None:
            return {'message': 'Recipe not found'}, HTTPStatus.NOT_FOUND
        if recipe.user_id != get_jwt_identity():
            return {'message': 'Access is not allowed'}, HTTPStatus.FORBIDDEN

        if recipe.cover_image:
            cover_image_path = image_set.path(recipe.cover_image,
                                              folder='cover_images')
            if os.path.exists(cover_image_path):
                os.remove(cover_image_path)
        filename = save_image(file, 'cover_images')
        recipe.cover_image = filename
        recipe.save()
        clear_cache('/recipes')
        return recipe_cover_schema.dump(recipe).data, HTTPStatus.OK
Example #31
0
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({
                'status': 'error',
                'error': 'User not found'
            })
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({
                'status': 'error',
                'error': 'Recipe not found'
            })
            return

        new_recipe = Recipe(**{
            'owner': self.user,
            'cloned_from': recipe,
            'color': recipe.color,
            'ibu': recipe.ibu,
            'alcohol': recipe.alcohol,
            'name': recipe.name,
            'description': recipe.description,
            'type': recipe.type,
            'category': recipe.category,
            'style': recipe.style,
            'batch_size': recipe.batch_size,
            'boil_size': recipe.boil_size,
            'bottling_temp': recipe.bottling_temp,
            'bottling_pressure': recipe.bottling_pressure,
            'steep_efficiency': recipe.steep_efficiency,
            'mash_efficiency': recipe.mash_efficiency,
            'primary_days': recipe.primary_days,
            'primary_temp': recipe.primary_temp,
            'secondary_days': recipe.secondary_days,
            'secondary_temp': recipe.secondary_temp,
            'tertiary_days': recipe.tertiary_days,
            'tertiary_temp': recipe.tertiary_temp,
            'aging_days': recipe.aging_days,
            '_ingredients': recipe._ingredients
        })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()
        new_recipe.update_grade()
        new_recipe.put()

        # Update recipe ranking for sorting
        recipe.update_grade()
        recipe.put()

        action = UserAction()
        action.owner = self.user
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({
            'status': 'ok',
            'redirect': new_recipe.url
        })
Example #32
0
class RecipeTest(unittest.TestCase, Categories):
    """ Class performing unit testing for class Recipe"""
    def setUp(self):
        """Defining setUp() method that runs prior to each test."""
        self.newRecipe = Recipe()
        self.newCategory = Categories()
        self.recipe_register = self.newRecipe.recipe_register(
            "category", "recipe", "*****@*****.**", "recipe_ingredients",
            "recipe_methods")
        self.newCategory.category_register("category_one", "*****@*****.**")
        app.config['TESTING'] = True
        self.test_app = app.test_client()

    def test_recipe_register_route(self):
        """ Test to check if recipe register route works"""
        response = self.test_app.get('/recipe_register')
        self.assertEqual(response.status_code, 200)

    def test_recipe_registration(self):
        """ Test for method create recipe """
        recipe_success_registration = self.newRecipe.recipe_register(
            "category_one", "recipee", "*****@*****.**",
            "recipe_ingredients", "recipe_methods")
        self.assertEqual("successfully created recipe",
                         recipe_success_registration)

    def test_recipe_regex_match(self):
        """ Test for recipe name regex match """
        recipe_name_regex_format = self.newRecipe.recipe_register(
            "category", "@@@", "*****@*****.**", "recipe_ingredients",
            "recipe_methods")
        self.assertEqual("Recipe name has special characters",
                         recipe_name_regex_format)

    def test_recipe_null_name(self):
        """ Test for null recipe name  """
        recipe_null_name = self.newRecipe.recipe_register(
            "category", "", "*****@*****.**", "recipe_ingredients",
            "recipe_methods")
        self.assertEqual("Null recipe name", recipe_null_name)

    def test_recipe_null_ingredients(self):
        """ Test for null recipe ingredients """
        recipe_null_ingredients = self.newRecipe.recipe_register(
            "category", "recipe_name", "*****@*****.**", "",
            "recipe_methods")
        self.assertEqual("Null recipe ingredients", recipe_null_ingredients)

    def test_recipe_null_methods(self):
        """ Test for null recipe preparation methods  """
        recipe_null_methods = self.newRecipe.recipe_register(
            "category", "recipe_name", "*****@*****.**",
            "recipe_ingredients", "")
        self.assertEqual("Null recipe method", recipe_null_methods)

    def test_recipe_exists(self):
        """ Test for method if recipe exists """
        recipe_exists = self.newRecipe.recipe_register("category", "recipe",
                                                       "*****@*****.**",
                                                       "recipe_ingredients",
                                                       "recipe_methods")
        self.assertEqual("Recipe exists", recipe_exists)

    def test_recipe_edit_route(self):
        """ Test to check if recipe edit route works"""
        response = self.test_app.get('/recipe_edit/Panckakes')
        self.assertEqual(response.status_code, 200)

    def test_edit_recipe_regex_format(self):
        """ Test for recipe name regex pattern name on update  """
        edit_recipe_regex = self.newRecipe.recipe_edit("@@@", "recipe_name",
                                                       "category_one", "mwaz",
                                                       "recipe_ingredients",
                                                       "recipe_methods")
        self.assertEqual("Recipe name has special characters",
                         edit_recipe_regex)

    def test_edit_recipe_is_null(self):
        """ Test for null recipe name on update  """
        recipe_edit_is_null = self.newRecipe.recipe_edit(
            "", "categoryone", "recipe_name", "mwaz", "recipe_ingredients",
            "recipe_methods")
        self.assertEqual("Null recipe name", recipe_edit_is_null)

    def succss_recipe_name_edit(self):
        """ Test for successful recipe name on update  """
        recipe_edit_success = self.newRecipe.recipe_edit(
            "new_recipe", "categoryone", "recipe_name", "mwaz",
            "recipe_ingredients", "recipe_methods")
        self.assertEqual("Successfully edited recipe", recipe_edit_success)

    def test_recipe_delete_route(self):
        """ Test to check if recipe delete route works"""
        response = self.test_app.get('/recipe_delete')
        self.assertEqual(response.status_code, 200)
Example #33
0
    def get(self, q, page, per_page):

        paginated_recipes = Recipe.get_all_published(q, page, per_page)

        return recipe_pagination_schema.dump(
            paginated_recipes).data, HTTPStatus.OK
Example #34
0
    def process(self, action, username=None, recipe_slug=None):
        """
        Process a request to add or remove a user from the liked list.
        """
        user = UserPrefs.get()
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({
                'status': 'error',
                'error': 'User not found'
            })
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({
                'status': 'error',
                'error': 'Recipe not found'
            })
            return

        if action == 'post':
            if user.user_id not in recipe.likes:
                recipe.likes.append(user.user_id)
                recipe.put()

                existing = UserAction.all()\
                                     .filter('owner =', user)\
                                     .filter('type =', UserAction.TYPE_RECIPE_LIKED)\
                                     .filter('object_id =', recipe.key().id())\
                                     .count()

                if not existing:
                    user_action = UserAction()
                    user_action.owner = user
                    user_action.type = user_action.TYPE_RECIPE_LIKED
                    user_action.object_id = recipe.key().id()
                    user_action.put()

        elif action == 'delete':
            if user.user_id in recipe.likes:
                recipe.likes.remove(user.user_id)
                recipe.put()

                existing = UserAction.all()\
                                     .filter('owner =', user)\
                                     .filter('type =', UserAction.TYPE_RECIPE_LIKED)\
                                     .filter('object_id =', recipe.key().id())\
                                     .get()

                if existing:
                    existing.delete()

        return self.render_json({
            'status': 'ok',
            'likes': len(recipe.likes)
        })
Example #35
0
def seed_database(debug=False):
    """
    WARNING: This will NOT create the tables for you if you
    dropped your entire database. You must re-create the database
    then run 'Base.metadata.create_all(<engine>)' to create your
    tables then you can run this without an issue!

    IMPORTANT: You need to import Base from models.models or else
    SQLAlchemy won't know about the models and therefore will NOT
    create the proper tables in your database which will cause this
    function to fail.

    Create data in the database by randomly generating values.
    Once this function is complete, it will write data that is
    likely to be used in testing to the 'seeded_objects_info.txt'
    file with separators and linebreaks to make it easier to read.

    When a user instance is created, its subsequent Profile is created
    as well and then they are associated with one another.
    After the user and profile objects are created, create some recipe
    objects to be associated with the profile object. Leave some profile
    objects without any recipes for filter testing.
    """
    if debug:
        # If something happened during object creation
        # we'll get a UNIQUE CONSTRAINT FAILED error
        # when trying again so, delete all the records
        # in the database and try to create the objects.
        # so we can preserve the existing tables
        from models.base_model import Base
        from db import engine
        for tbl in reversed(Base.metadata.sorted_tables):
            engine.execute(tbl.delete())

    # Create how ever many user and profile objects the user defined
    user_dicts = [
        {
            'street_address': "777 Brockton Avenue",
            'city': "Abington",
            "state_or_province": "Massachusetts",
            'country': "United States",
            'zip_code': "01001",
            'email': "*****@*****.**",
            'password': "******",
        },
        {
            'street_address': "30 Memorial Drive",
            'city': "Avon",
            'state_or_province': "Massachusetts",
            'country': "United States",
            'zip_code': "20194",
            'email': "*****@*****.**",
            'password': "******"
        },
        {
            'street_address': "250 Hartford Avenue",
            'city': "Toronto",
            'state_or_province': "Ontario",
            'country': "Canada",
            'zip_code': "A1A 1A1",
            'email': "*****@*****.**",
            'password': "******"
        },
    ]
    profile_dicts = [{
        'name': "Giuseppe",
        "is_chef": True,
        "about_me":
        "I love to cook and have been doing so for 15 years. My specialty is Italian food",
        "location": "Massachusettes, United States",
        'profile_image':
        "https://images.unsplash.com/photo-1600565193348-f74bd3c7ccdf?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80",
        'favourite_recipe':
        "Spicy Pork Tenderloin with Apples and Sweet Potatoes",
        'favourite_cuisine': "italian,",
    }, {
        'name': "Mario",
        "is_chef": False,
        'about_me':
        "I love food, if I could eat every hour of the day I would.",
        "location": "Massachusettes, United States",
        'profile_image':
        "https://images.unsplash.com/photo-1521341057461-6eb5f40b07ab?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80",
        'favourite_cuisine': "thai,",
    }, {
        'name': "Tessa",
        "is_chef": False,
        'about_me':
        "I'm not a chef but wish I was, I couldn't boil noodles without burning them!",
        "location": "Ontario, Canada",
        'profile_image':
        "https://images.unsplash.com/photo-1505999407077-7937810b98ae?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1188&q=80",
        'favourite_cuisine': "Mexican,"
    }]

    recipe_dicts = [
        {
            'name':
            'Spicy Pork Tenderloin with Apples and Sweet Potatoes',
            'description':
            "A spicy pork tenderloin with delicious green apples and sweet potatoes",
            'available':
            True,
            'cuisine':
            "french",
            'price':
            1000,
            'ingredients':
            "Pork Tenderloin,Green Apples,Sweet Potatoes,Rosemary",
            'required_items':
            "Dinner Plate, Kitchen Table, Oven",
            'image_urls':
            "https://images.unsplash.com/photo-1598514982205-f36b96d1e8d4?ixid=MXwxMjA3fDB8MHxzZWFyY2h8M3x8cG9yayUyMHRlbmRlcmxvaW58ZW58MHx8MHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=60https://images.unsplash.com/photo-1598514982205-f36b96d1e8d4?ixid=MXwxMjA3fDB8MHxzZWFyY2h8M3x8cG9yayUyMHRlbmRlcmxvaW58ZW58MHx8MHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=60,"
        },
        {
            'name':
            "Al's Burmese Chicken Curry",
            'description':
            "Chicken",
            'available':
            False,
            'cuisine':
            "indian",
            'price':
            1000,
            'ingredients':
            "Pork Tenderloin,Green Apples,Sweet Potatoes,Rosemary",
            'required_items':
            "Dinner Plate,Kitchen Table,Oven",
            'image_urls':
            "https://images.unsplash.com/photo-1501200291289-c5a76c232e5f?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxleHBsb3JlLWZlZWR8M3x8fGVufDB8fHw%3D&auto=format&fit=crop&w=1000&q=60,"
        },
        {
            'name':
            "Sweet Potato and Venison Shepherd's Pie",
            'description':
            "Shepherds Pie stuffed with sweet potatoes and venison, cooked to golden perfection",
            'available':
            True,
            'cuisine':
            "french",
            'price':
            2000,
            'ingredients':
            "Venison,Sweet potatoes,Gravy",
            'required_items':
            "Dinner Plate,Oven",
            'image_urls':
            "https://images.unsplash.com/photo-1600626336264-60ef2a55bd33?ixid=MXwxMjA3fDB8MHxzZWFyY2h8NHx8c2hlcGhlcmRzJTIwcGllfGVufDB8fDB8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=60,"
        },
        {
            'name':
            "Gemelli Pasta with Roasted Pumpkin and Pancetta",
            "description":
            "Delicious pasta smothered in Pancetta with Roasted Pumpkin",
            'available':
            False,
            'cuisine':
            "italian",
            'price':
            1500,
            'ingredients':
            "Roasted Pumpkin,Pasta,Pancetta",
            'required_items':
            "Large Pot,Stove,Dinner Table",
            'image_urls':
            "https://images.unsplash.com/photo-1579631542720-3a87824fff86?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80,"
        },
        {
            'name':
            "Beef Stroganoff with Ground Beef",
            'description':
            "Beef stroganoff filled with ground beef, served with a delicious buttery dinner roll",
            'available':
            True,
            'cuisine':
            "turkish",
            'price':
            2500,
            'ingredients':
            "Ground Beef,Brown Gravy,Wide Egg Noodles,",
            'required_items':
            "Large Pot,Stove Top,Oven",
            'image_urls':
            "https://images.unsplash.com/photo-1504669221159-56caf7b07f57?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80,",
        },
    ]
    last_user = None
    for index in range(len(user_dicts)):
        print(index)
        new_user = User.create(**user_dicts[index])
        # Create profile
        new_profile = Profile()
        new_profile = new_profile.create(**profile_dicts[index])

        # Assign the new profile to the new user
        new_user.assign_one_to_one('profile', new_profile)

        # If we have another user, create messages between the
        # last one and the new one
        if last_user != None:
            new_conversation = Conversation.create(**{
                'user_one': last_user,
                'user_two': new_user
            })
            # Create messages for the two users
            last_users_message = Message.create(
                **{
                    'sender': last_user,
                    'content': "Hello %s how are you?" %
                    (new_user.profile.name)
                })
            new_users_message = Message.create(
                **{
                    'sender':
                    new_user,
                    'content':
                    "I'm good %s how about you?" % (last_user.profile.name)
                })
            # Add messages to the conversation
            new_conversation.add_to_relationship('messages',
                                                 last_users_message)
            new_conversation.add_to_relationship('messages', new_users_message)
            # Create 5 recipes for each user/profile
        new_recipe = Recipe.create(**recipe_dicts[index])
        # Add the new recipe to the One to Many field in the Profile model
        new_profile.add_to_relationship('recipes', new_recipe)
        last_user = new_user
    print_info(user_dicts, profile_dicts, recipe_dicts)
Example #36
0
def recipes_view():
    recipe_list = Recipe.get_by_owner(g.user.username)
    return render_template('view_recipes.html', recipe_list=recipe_list)
Example #37
0
def delete_recipe(**kwargs):
    response_dict = {}
    recipe_id = request.get_json().get('recipe_id')
    try:
        recipe = Recipe.get_instance(**{'id': recipe_id})
        kwargs['user'].profile.remove_from_relationship('recipes', recipe)
        Recipe.delete(recipe_id)
        response_dict['status'] = 200
        response_dict['message'] = "Recipe successfully deleted"
        return jsonify(response_dict), 200
   except AssertionError as e:
       response_dict['status'] = 400
       response_dict['message'] = "%s" % (e)
       return jsonify(response_dict), 400


# The following 2 endpoints could possibly be
# merged into one. This depends on the front
# end design when it comes to editing information
@app.route("/user/edit",methods=["PUT"])
@authenticate
def edit_user():
    """
    I'm not sure if I need to return the updated
    information or not. The front end can use the
    given values to udpate the display as long 
    as the status is 200. If the front end will
    re-render, this is not a concern. Otherwise 
    this needs to return a new user information dictionary
    """
    request_dict = request.form.to_dict()
    user_info = {}
    for field in User.get_fields():
        if request_dict.get(field, None) != None:
            user_info[field] = request_dict.get(field)
    try:
        User.update(user.id,**user_info)
        # An updated user information dictionary will
        # be returned on next re-render
        response_dict['status'] = 200
        response_dict['message'] = "Successfully updated information"
        return jsonify(response_dict), 200
    except AssertionError as e:
        # Validation problem
        response_dict['status'] = 400
        response_dict['message'] = "%s" % (e)
        return jsonify(response_dict), 400

@app.route('/profile/edit', methods=["PUT"])
@authenticate
def edit_profile(**kwargs):
    response_dict = {}
    request_dict = request.get_json()
    new_info = {}
    for field in Profile.get_fields():
        if request_dict.get(field, None) != None:
            new_info[field] = request_dict.get(field)
    try:
        Profile.update(user.profile.id, **new_info)
        response_dict['status'] = 200
        response_dict['message'] = "Successfully updated profile"
        return jsonify(response_dict), 200
    except AssertionError as e:
        response_dict['status'] = 400
        response_dict['message'] = "%s" % (e)
        return jsonify(response_dict), 400
Example #38
0
        # Parse the JSON into Python objects
        try:
            recipe_data = json.loads(recipe_json)
        except Exception, e:
            self.render_json({
                'status': 'error',
                'error': str(e),
                'input': recipe_json
            })
            return

        # Load recipe from db or create a new one
        new_recipe = False
        if not recipe_slug:
            recipe = Recipe()
            recipe.owner = user
            new_recipe = True
        else:
            recipe = Recipe.all()\
                           .filter('owner =', user)\
                           .filter('slug =', recipe_slug)\
                           .get()

            if not recipe:
                self.render_json({
                    'status': 'error',
                    'error': 'Recipe not found'
                })
                return
Example #39
0
# CREATING A USER AND A RECIPE
from app import *

from models.user import User

from models.recipe import Recipe

app = create_app()

with app.app_context():
    user = User(username='******', email='*****@*****.**', password='******')
    
    db.session.add(user)
    db.session.commit()
    
    encebollado = Recipe(name='Encebollado', description='El encebollado es un plato típico ecuatoriano originario de la región costa', num_of_servings=1, cook_time=30, directions='hay que conseguir albacora', user_id=user.id)
    lasagnia = Recipe(name='lasaña', description='La lasaña es un tipo de pasta que se sirve en láminas para denominarse lasaña ha de llevar ', num_of_servings=1, cook_time=30, directions='Las laminas paso 1', user_id=user.id)

    db.session.add(encebollado)
    db.session.add(lasagnia)
    db.session.commit()
    
    user = User.query.filter_by(username='******').first()
    
    for recipe in user.recipes:
        print('{} recipe made by {} can serve {} people.'.format(recipe.name, recipe.user.username, recipe.num_of_servings))
Example #40
0
    def get(self):
        user = self.user

        # Try to get rendered output from memcache
        rendered = memcache.get('dashboard-' + user.user_id)
        if rendered and not settings.DEBUG:
            return self.response.out.write(rendered)

        # Fetch following users
        following = user.following_users\
                        .order('name')\
                        .fetch(100)

        user_keys = [user.key()] + [u.key() for u in following]

        # Start async fetch of top recipes
        top_recipes = Recipe.all()\
                            .filter('owner IN', user_keys)\
                            .order('-grade')\
                            .run(limit=15)

        # Get and process interesting events
        interesting_events = UserAction.all()\
                                       .filter('owner IN', user_keys)\
                                       .order('-created')\
                                       .fetch(15)

        object_ids = UserAction.gather_object_ids(interesting_events)
        object_ids['users'] = [id for id in object_ids['users'] if id not in [user.key().id()] + user.following]

        # Start async fetch of relevant recipes
        recipes = db.get_async([Key.from_path('Recipe', id) for id in object_ids['recipes']])

        # Start async fetch of relevant brews
        brews = db.get_async([Key.from_path('Brew', id) for id in object_ids['brews']])

        # Convert iterators to  lists of items in memory and setup a map
        # of user id -> user for easy lookups
        following = list(following)
        top_recipes = list(top_recipes)

        user_map = {
            user.key().id(): user
        }

        for u in following:
            user_map[u.key().id()] = u

        if object_ids['users']:
            for u in UserPrefs.get_by_id(object_ids['users']):
                user_map[u.key().id()] = u

        # Setup a map of brew id -> brew for easy lookups
        brew_map = {}
        brew_recipe_ids = set()

        for b in brews.get_result():
            brew_recipe_ids.add(b.recipe_key.id())
            brew_map[b.key().id()] = b

        # Async fetch of any recipes brews reference that weren't
        # included in the recipe fetch above...
        brew_recipes = db.get_async([Key.from_path('Recipe', id) for id in brew_recipe_ids if id not in object_ids['recipes']])

        # Setup a map of recipe id -> recipe for easy lookups
        recipe_map = {}

        for r in recipes.get_result():
            recipe_map[r.key().id()] = r

        for r in brew_recipes.get_result():
            recipe_map[r.key().id()] = r

        # Render and cache for 1 minute
        memcache.set('dashboard-' + user.user_id, self.render('dashboard.html', {
            'following': following,
            'user_map': user_map,
            'recipe_map': recipe_map,
            'brew_map': brew_map,
            'top_recipes': top_recipes,
            'interesting_events': interesting_events
        }), self.CACHE_TIME)
Example #41
0
def edit(recipe_id):
    recipe = Recipe.get_or_none(Recipe.id == recipe_id)
    return render_template('recipes/edit.html', recipe_id=recipe.id)
Example #42
0
def index():
    recipes = Recipe.select()
    return render_template("index.html", recipes=recipes)
Example #43
0
def read_recipe(recipe_id):
	form = UpdateRecipeForm()
	that_recipe = Recipe.get_or_none(Recipe.id == recipe_id)
	recipe_user_id = that_recipe.user_id
	return render_template('read_that_recipe.html', recipe=that_recipe, form=form, user=recipe_user_id)
Example #44
0
    def get(self):
        user = self.user

        # Try to get rendered output from memcache
        rendered = memcache.get('dashboard-' + user.user_id)
        if rendered and not settings.DEBUG:
            return self.response.out.write(rendered)

        # Fetch following users
        following = user.following_users\
                        .order('name')\
                        .fetch(100)

        user_keys = [user.key()] + [u.key() for u in following]

        # Start async fetch of top recipes
        top_recipes = Recipe.all()\
                            .filter('owner IN', user_keys)\
                            .order('-grade')\
                            .run(limit=15)

        # Get and process interesting events
        interesting_events = UserAction.all()\
                                       .filter('owner IN', user_keys)\
                                       .order('-created')\
                                       .fetch(15)

        object_ids = UserAction.gather_object_ids(interesting_events)
        object_ids['users'] = [
            id for id in object_ids['users']
            if id not in [user.key().id()] + user.following
        ]

        # Start async fetch of relevant recipes
        recipes = db.get_async(
            [Key.from_path('Recipe', id) for id in object_ids['recipes']])

        # Start async fetch of relevant brews
        brews = db.get_async(
            [Key.from_path('Brew', id) for id in object_ids['brews']])

        # Convert iterators to  lists of items in memory and setup a map
        # of user id -> user for easy lookups
        following = list(following)
        top_recipes = list(top_recipes)

        user_map = {user.key().id(): user}

        for u in following:
            user_map[u.key().id()] = u

        if object_ids['users']:
            for u in UserPrefs.get_by_id(object_ids['users']):
                user_map[u.key().id()] = u

        # Setup a map of brew id -> brew for easy lookups
        brew_map = {}
        brew_recipe_ids = set()

        for b in brews.get_result():
            brew_recipe_ids.add(b.recipe_key.id())
            brew_map[b.key().id()] = b

        # Async fetch of any recipes brews reference that weren't
        # included in the recipe fetch above...
        brew_recipes = db.get_async([
            Key.from_path('Recipe', id) for id in brew_recipe_ids
            if id not in object_ids['recipes']
        ])

        # Setup a map of recipe id -> recipe for easy lookups
        recipe_map = {}

        for r in recipes.get_result():
            recipe_map[r.key().id()] = r

        for r in brew_recipes.get_result():
            recipe_map[r.key().id()] = r

        # Render and cache for 1 minute
        memcache.set(
            'dashboard-' + user.user_id,
            self.render(
                'dashboard.html', {
                    'following': following,
                    'user_map': user_map,
                    'recipe_map': recipe_map,
                    'brew_map': brew_map,
                    'top_recipes': top_recipes,
                    'interesting_events': interesting_events
                }), self.CACHE_TIME)
Example #45
0
    def get(self, username=None, recipe_slug=None, version=None):
        """
        Render the recipe view. If no slug is given then create a new recipe
        and render it in edit mode.
        """
        # Create a new recipe if we have no slug, otherwise query
        if not recipe_slug:
            publicuser = self.user
            recipe = Recipe()
            recipe.owner = publicuser
            recipe.new = True
            brews = []
        else:
            publicuser = UserPrefs.all().filter('name =', username).get()

            if not publicuser:
                self.abort(404)

            recipe = Recipe.all()\
                           .filter('owner =', publicuser)\
                           .filter('slug =', recipe_slug)\
                           .get()

            if not recipe:
                self.abort(404)

            brews = recipe.brews.order('-started').fetch(3)

            if version:
                try:
                    version = int(version)
                except:
                    self.abort(404)

                history = RecipeHistory.get_by_id(version, recipe)

                if not history:
                    self.abort(404)

                recipe.old = True
                recipe.oldname = history.name
                recipe.description = history.description
                recipe.type = history.type
                recipe.category = history.category
                recipe.style = history.style
                recipe.batch_size = history.batch_size
                recipe.boil_size = history.boil_size
                recipe.bottling_temp = history.bottling_temp
                recipe.bottling_pressure = history.bottling_pressure
                recipe.mash_efficiency = history.mash_efficiency
                recipe.steep_efficiency = history.steep_efficiency
                recipe.primary_days = history.primary_days
                recipe.secondary_days = history.secondary_days
                recipe.tertiary_days = history.tertiary_days
                recipe.aging_days = history.aging_days
                recipe._ingredients = history._ingredients

        cloned_from = None
        try:
            cloned_from = recipe.cloned_from
        except Exception, e:
            pass
Example #46
0
def new():

    name = request.form.get('name', None)
    directions = request.form.get('directions', None)
    ingredients = request.form.get('ingredients', None)
    countrys = request.form.get('countrys', None)
    hour = request.form.get('hour', None)
    sec = request.form.get('sec', None)
    time = request.form.get('time', None)

    numHour = int(hour)
    numMin = int(sec) / 100
    prepTime = numHour + numMin

    photo = request.files['photo']
    photoName = time + photo.filename
    client = storage.Client()
    bucket = client.get_bucket('foody-project')
    myBlob = bucket.blob(photoName)
    myBlob.upload_from_string(photo.read())

    id = get_jwt_identity()

    recipe = Recipe(
        name=name,
        photo=myBlob.public_url,
        directions=directions,
        ingredients=ingredients,
        hour=hour,
        sec=sec,
        prep=prepTime,
        countrys=countrys,
        time=time,
        user=id,
    )
    recipe.save()

    user = User.get_or_none(User.id == id)
    recipes = Recipe.select().where(Recipe.user_id == id)

    # url_photo = recipe.photo
    my_recipes = Recipe.select().where(Recipe.user_id == id)
    recipesNum = len([c.id for c in my_recipes])

    return jsonify({
        "status":
        "success",
        "recipesNum":
        recipesNum,
        "recipes": [{
            "id": recipe.id,
            "name": recipe.name,
            "photo": recipe.photo,
            "countrys": recipe.countrys,
            "hour": recipe.hour,
            "sec": recipe.sec,
            "directions": recipe.directions,
            "ingredients": recipe.ingredients,
            "time": recipe.time,
            "username": user.username,
            "user_id": user.id,
            "user_photo": user.photo
        } for recipe in recipes]
    }), 200
Example #47
0
    def get(self, username=None, recipe_slug=None):
        """
        Render the basic recipe history list for the given recipe.
        """
        if not username or not recipe_slug:
            self.abort(404)

        publicuser = UserPrefs.all().filter('name =', username).get()
        if not publicuser:
            self.abort(404)

        recipe = Recipe.all()\
                       .filter('slug = ', recipe_slug)\
                       .filter('owner =', publicuser)\
                       .get()
        if not recipe:
            self.abort(404)

        history = RecipeHistory.all()\
                        .ancestor(recipe)\
                        .order('-created')\
                        .fetch(20)

        # The list of entries we'll use to populate the template along with
        # the current recipe as the first entry
        entries = [{
            'recipe': recipe,
            'edited': recipe.edited,
            'slug': recipe.slug,
            'customtag': 'Most Recent',
            'show_snippet': True
        }]

        # Check if there is any history to diff with
        if len(history) > 0:
            entries[0]['differences'] = self.delete_ignored_keys(recipe.diff(history[0]))
        else:
            entries[0]['first'] = True

        # Get a list of differences in the history. Use reduce with a function
        # that returns the right operand to simply find pairwise differences.
        differences = []
        def diff(left, right):
            differences.append(left.diff(right))
            return right
        # Make sure reduce isn't called with no history (throws exception)
        reduce(diff, history) if len(history) > 0 else None

        # Start going through the history looking at differences to decide how
        # we plan on displaying the info to the user (using a snippet or not)
        for i in range(len(differences)):
            # Make sure this entry has differences before further processing
            if self.is_empty(differences[i]):
                continue

            # Set some required properties for the snippet to work
            history[i].owner = publicuser
            history[i].slug = recipe.slug + '/history/' + str(history[i].key().id())

            # Create the entry
            entry = {
                'recipe': history[i],
                'differences': self.delete_ignored_keys(differences[i]),
                'edited': history[i].created,
                'slug': history[i].slug,
                'show_snippet': False
            }

            # Check if the name or description changed and we should show
            # a snippet
            for snippetItem in RecipeHistoryHandler.SNIPPET_ITEMS:
                if snippetItem in differences[i][2]:
                    entry['show_snippet'] = True
                    # Make sure the color, ibu, and alcohol were created
                    if not hasattr(history[i], 'color'):
                        history[i].update_cache()
                    break

            # Save the entry
            entries.append(entry)

        # Add the final entry only if it's the original recipe, otherwise it
        # will be a version that should have diffs but we didn't generate any.
        if len(history) > 0:
            last = history[-1]
            delta = timedelta(seconds=1)
            if recipe.created - delta < last.created < recipe.created + delta:
                last.owner = publicuser
                last.slug = recipe.slug + '/history/' + str(last.key().id())
                if not hasattr(last, 'color'):
                    last.update_cache()
                entries.append({
                    'recipe': last,
                    'edited': last.created,
                    'slug': last.slug,
                    'customtag': 'Original',
                    'first': True
                })

        # Perform a second pass in reverse to check for large changes that
        # should show up as a snippet but were missed in the pairwise
        # checking above.
        entries[-1]['show_snippet'] = True
        for i in range(len(entries) - 1, 0, -1):
            # Check if the snippet is already showing
            if entries[i]['show_snippet']:
                last_snippet = entries[i]['recipe']
                continue

            # Check if the name, description, color, ibu, or alcohol changed
            # and we should show a snippet
            for snippetItem in RecipeHistoryHandler.IGNORED_KEYS:
                if not hasattr(entries[i]['recipe'], snippetItem):
                    continue 
                
                attr = getattr(entries[i]['recipe'], snippetItem)
                if type(attr) != int and type(attr) != float:
                    continue

                # See if the change was more than 10%, then show the
                # snippet, else show the orb
                try:
                    change = float(attr) / getattr(last_snippet, snippetItem)
                except:
                    change = 2
                logging.info(snippetItem)
                logging.info(change)
                if change < 0.9 or change > 1.1:
                    last_snippet = entries[i]['recipe']
                    entries[i]['show_snippet'] = True
                    break

        # Stop the template from performing another query for the username
        # when it tries to render the recipe
        recipe.owner = publicuser

        self.render('recipe-history.html', {
            'publicuser': publicuser,
            'recipe': recipe,
            'entries': entries
        })
Example #48
0
def show_search():
    id = get_jwt_identity()
    favorites = Favorite.select().join(
        User,
        on=Favorite.user_id).switch(Favorite).where(Favorite.user_id == id)
    excluded_chefs = [c.chef_id for c in favorites]

    hour = request.args.get('hour')
    sec = request.args.get('sec')
    country = request.args.get('country')
    order = request.args.get('order')

    if order == "Time to prepare":
        ooo = Recipe.prep
    elif order == "":
        ooo = Recipe
    elif order == "Recently":
        ooo = Recipe.created_at.desc()

    prepTime = None
    if sec and hour:
        prepTime = int(hour) + (int(sec) / 100)
    elif sec:
        prepTime = (int(sec) / 100)
    elif hour:
        prepTime = int(hour)

    recipes = False
    if country and prepTime:
        recipes = Recipe.select().where(
            (Recipe.countrys == country) & (Recipe.user_id != id)
            & (Recipe.prep <= prepTime)
            & Recipe.user_id.not_in(excluded_chefs)).order_by(ooo)
    elif country:
        recipes = Recipe.select().where(
            (Recipe.countrys == country) & (Recipe.user_id != id)
            & Recipe.user_id.not_in(excluded_chefs)).order_by(ooo)
    elif prepTime:
        recipes = Recipe.select().where(
            (Recipe.prep <= prepTime) & (Recipe.user_id != id)
            & Recipe.user_id.not_in(excluded_chefs)).order_by(ooo)
    else:
        recipes = Recipe.select().where(
            (Recipe.user_id != id)
            & Recipe.user_id.not_in(excluded_chefs)).order_by(ooo)

    if recipes:
        return jsonify({
            "status":
            "success",
            "recipe": [{
                "id": recipe.id,
                "name": recipe.name,
                "photo": recipe.photo,
                "countrys": recipe.countrys,
                "hour": recipe.hour,
                "sec": recipe.sec,
                "directions": recipe.directions,
                "ingredients": recipe.ingredients,
                "time": recipe.time,
                "username": recipe.user.username,
                "user_id": recipe.user.id,
                "id_owner": recipe.user.id,
                "user_photo": recipe.user.photo
            } for recipe in recipes]
        }), 200
    else:
        return jsonify({"recipe": [], "status": "no recipe"}), 200
Example #49
0
        recipe_json = cgi.escape(self.request.get('recipe'))

        # Parse the JSON into Python objects
        try:
            recipe_data = json.loads(recipe_json)
        except Exception, e:
            self.render_json({
                'status': 'error',
                'error': str(e),
                'input': recipe_json
            })
            return

        # Load recipe from db or create a new one
        if not recipe_slug:
            recipe = Recipe()
            recipe.owner = user
        else:
            recipe = Recipe.all()\
                           .filter('owner =', user)\
                           .filter('slug =', recipe_slug)\
                           .get()

            if not recipe:
                self.render_json({
                    'status': 'error',
                    'error': 'Recipe not found'
                })
                return

        # Ensure you own this recipe
Example #50
0
        # Parse the JSON into Python objects
        try:
            recipe_data = json.loads(recipe_json)
        except Exception, e:
            self.render_json({
                'status': 'error',
                'error': str(e),
                'input': recipe_json
            })
            return

        # Load recipe from db or create a new one
        new_recipe = False
        if not recipe_slug:
            recipe = Recipe()
            recipe.owner = user
            new_recipe = True
        else:
            recipe = Recipe.all()\
                           .filter('owner =', user)\
                           .filter('slug =', recipe_slug)\
                           .get()

            if not recipe:
                self.render_json({
                    'status': 'error',
                    'error': 'Recipe not found'
                })
                return
Example #51
0
    def get(self):

        recipes = Recipe.get_all_published()

        return recipe_list_schema.dump(recipes).data, HTTPStatus.OK
Example #52
0
blueberries = Ingredient(
    name='blueberries',
    image=
    'https://images.unsplash.com/photo-1520605363242-1012f0ae0c15?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=925&q=80',
    nutrition_information=
    '3.6 g dietary fiber, or 14.4 percent of your daily value (DV), 9 milligrams (mg) calcium, 0.9 percent DV., 9 mg magnesium, 2.25 percent DV., 114 mg potassium, 2.42 percent DV., 14.4 mg vitamin C, 24 percent DV., 9 micrograms (mcg) folate, 2.25 percent DV.'
)
db.session.add(blueberries)

#RECIPES
banana_carrot_seed_bread = Recipe(
    name='Banana, Carrot and Seed Bread',
    image=
    'https://images.unsplash.com/photo-1547033964-1be30700c397?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
    extra_ingredients=
    '150g / 5oz softened unsalted butter, 2 large eggs, 200g/ 7oz ripe bananas, peeled and mashed, 125g / 4½oz grated carrot, 25g / 1oz sultanas, 125g / 4½oz soft dark brown sugar, 225g / 8oz self-raising flour, ½ teaspoon ground cinnamon, 1 teaspoon mixed spice, 1 teaspoon ground ginger, 25g / 1oz pumpkin seeds, 25g / 1oz sunflower seeds, Butter, for spreading and greasing',
    method=
    '1.Preheat the oven to 170°C/340°F/Gas 3, grease a 900 g/2 lb loaf tin and line it with baking parchment.2.Place all of the ingredients, except the topping, in a large mixing bowl. Whisk together with an electric hand-held whisk for 1–2 minutes until light and fluffy. Alternatively, use a stand mixer fitted with the paddle or whisk attachment. 3.Spoon the mixture into the tin and level out the top. 4.Sprinkle with the extra seeds and bake for 1–1¼ hours until golden, well risen and a skewer inserted comes out clean. 5.Remove from the oven and leave to cool on a wire rack, then remove from the tin. Dust with icing sugar (if using), cut into slices, spread with butter and serve.',
    ingredients=[banana, carrot])
db.session.add(banana_carrot_seed_bread)

carrot_cheese_muffins = Recipe(
    name='Carrot & Cheese Muffins',
    image=
    'https://images.unsplash.com/photo-1548693563-25dc13e7b2c1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
    extra_ingredients=
    '2 eggs, 175g self raising flour, 1 tsp baking powder, 100 ml milk,100g carrot, peeled and grated, 3 tbsp sunflower oil,1 tbsp chives, chopped,6 spring onions, sliced,1 tbsp fresh basil , chopped,50g parmesan, grated',
    method=
    '1.Preheat the oven to 180C Fan. Line a muffin tin with 10 muffin cases.2.Whisk the egg, flour, baking powder, milk and oil together in a large bowl. Add the carrot, herbs, spring onion and cheese and fold together. Spoon into the cases.3.Bake in the oven for 18 minutes until sell risen and lightly golden brown.',
    ingredients=[carrot, muffins])
Example #53
0
    def post(self, username=None, recipe_slug=None):
        publicuser = UserPrefs.all()\
                              .filter('name = ', username)\
                              .get()

        if not publicuser:
            self.render_json({'status': 'error', 'error': 'User not found'})
            return

        recipe = Recipe.all()\
                       .filter('owner =', publicuser)\
                       .filter('slug =', recipe_slug)\
                       .get()

        if not recipe:
            self.render_json({'status': 'error', 'error': 'Recipe not found'})
            return

        new_recipe = Recipe(
            **{
                'owner': self.user,
                'cloned_from': recipe,
                'color': recipe.color,
                'ibu': recipe.ibu,
                'alcohol': recipe.alcohol,
                'name': recipe.name,
                'description': recipe.description,
                'type': recipe.type,
                'category': recipe.category,
                'style': recipe.style,
                'batch_size': recipe.batch_size,
                'boil_size': recipe.boil_size,
                'bottling_temp': recipe.bottling_temp,
                'bottling_pressure': recipe.bottling_pressure,
                'steep_efficiency': recipe.steep_efficiency,
                'mash_efficiency': recipe.mash_efficiency,
                'primary_days': recipe.primary_days,
                'primary_temp': recipe.primary_temp,
                'secondary_days': recipe.secondary_days,
                'secondary_temp': recipe.secondary_temp,
                'tertiary_days': recipe.tertiary_days,
                'tertiary_temp': recipe.tertiary_temp,
                'aging_days': recipe.aging_days,
                '_ingredients': recipe._ingredients
            })

        new_recipe.slug = generate_usable_slug(new_recipe)
        new_recipe.put()
        new_recipe.update_grade()
        new_recipe.put()

        # Update recipe ranking for sorting
        recipe.update_grade()
        recipe.put()

        action = UserAction()
        action.owner = self.user
        action.type = action.TYPE_RECIPE_CLONED
        action.object_id = new_recipe.key().id()
        action.put()

        return self.render_json({'status': 'ok', 'redirect': new_recipe.url})
Example #54
0
 def get_all_recipes(self):
     response = []
     for rec in Recipe.objects():
         info = self._recipe_to_dict(rec)
         response.append(info)
     return json.dumps(response)
Example #55
0
def show():
    recipes = Recipe.select()
    return render_template('recipes/show.html', recipes=recipes)
Example #56
0
    def get(self, username=None, recipe_slug=None, version=None):
        """
        Render the recipe view. If no slug is given then create a new recipe
        and render it in edit mode.
        """
        # Create a new recipe if we have no slug, otherwise query
        if not recipe_slug:
            publicuser = self.user
            recipe = Recipe()
            recipe.owner = publicuser
            recipe.new = True
            brews = []
        else:
            publicuser = UserPrefs.all().filter('name =', username).get()

            if not publicuser:
                self.abort(404)

            recipe = Recipe.all()\
                           .filter('owner =', publicuser)\
                           .filter('slug =', recipe_slug)\
                           .get()

            if not recipe:
                self.abort(404)

            brews = recipe.brews.order('-started').fetch(3)

            if version:
                try:
                    version = int(version)
                except:
                    self.abort(404)

                history = RecipeHistory.get_by_id(version, recipe)

                if not history:
                    self.abort(404)

                recipe.old = True
                recipe.oldname = history.name
                recipe.description = history.description
                recipe.type = history.type
                recipe.category = history.category
                recipe.style = history.style
                recipe.batch_size = history.batch_size
                recipe.boil_size = history.boil_size
                recipe.bottling_temp = history.bottling_temp
                recipe.bottling_pressure = history.bottling_pressure
                recipe.mash_efficiency = history.mash_efficiency
                recipe.steep_efficiency = history.steep_efficiency
                recipe.primary_days = history.primary_days
                recipe.secondary_days = history.secondary_days
                recipe.tertiary_days = history.tertiary_days
                recipe.aging_days = history.aging_days
                recipe._ingredients = history._ingredients

        cloned_from = None
        try:
            cloned_from = recipe.cloned_from
        except Exception, e:
            pass
Example #57
0
    spring = Tag(name='Spring')
    autumn = Tag(name='Autumn')
    picnic = Tag(name='Picnic')
    easy = Tag(name='Easy')
    slowcooker = Tag(name='Slow cooker')
    onepot = Tag(name='One-pot')

    omelette = Recipe(
        name='Cheese and Spinach Omelette',
        cuisine=[french],
        ingredients=
        '["3 large eggs", "1 handful grated cheese of your choice", "small knob of butter", "salt & pepper to taste"]',
        chef=izzi,
        instructions=
        '["1. Whisk three large eggs in a bowl, salt and pepper to taste", "2. Grate the cheese and wash the spinach (if required)", "3. Heat the butter in a large frying pan over a medium heat. When the butter is fully melted and just starting to bubble, pour in the eggs. Ensure the mixture spreads evenly across the pan. Use a spatula to lift the edges slightly to let any liquid run under the omlette.", "4. When the base of the omlette is set but the top is still runny, add the cheese and allow to melt.", "5. Carefully lift one edge of the omlette - the underneath should be lightly browned. Add the spinach, fold the omlette in half and serve immediately."]',
        img=
        'https://www.cookforyourlife.org/wp-content/uploads/2018/08/Spinach-Omlette-696x465.jpg',
        video='video.link',
        liked_by=[charlie],
        tags=[quick, easy, budget],
        serves=1,
        prep_time_min=15,
        cook_time_min=15,
        description="A quick, easy lunch or dinner for any night of the week!")
    tuna_salad = Recipe(
        name='Tuna pasta salad',
        cuisine=[italian],
        chef=charlie,
        ingredients=
        '[ "200g dried pasta (approx 400g cooked)", "2 handfuls fresh rocket", "10 Peppadew or other sweet peppers", "150g cherry tomatoes", "Olive oil and balsamic for dressing"]',
        instructions=
Example #58
0
    def get(self, username=None, recipe_slug=None):
        """
        Render the basic recipe history list for the given recipe.
        """
        if not username or not recipe_slug:
            self.abort(404)

        publicuser = UserPrefs.all().filter('name =', username).get()
        if not publicuser:
            self.abort(404)

        recipe = Recipe.all()\
                       .filter('slug = ', recipe_slug)\
                       .filter('owner =', publicuser)\
                       .get()
        if not recipe:
            self.abort(404)

        history = RecipeHistory.all()\
                        .ancestor(recipe)\
                        .order('-created')\
                        .fetch(20)

        # The list of entries we'll use to populate the template along with
        # the current recipe as the first entry
        entries = [{
            'recipe': recipe,
            'edited': recipe.edited,
            'slug': recipe.slug,
            'customtag': 'Most Recent',
            'show_snippet': True
        }]

        # Check if there is any history to diff with
        if len(history) > 0:
            entries[0]['differences'] = self.delete_ignored_keys(
                recipe.diff(history[0]))
        else:
            entries[0]['first'] = True

        # Get a list of differences in the history. Use reduce with a function
        # that returns the right operand to simply find pairwise differences.
        differences = []

        def diff(left, right):
            differences.append(left.diff(right))
            return right

        # Make sure reduce isn't called with no history (throws exception)
        reduce(diff, history) if len(history) > 0 else None

        # Start going through the history looking at differences to decide how
        # we plan on displaying the info to the user (using a snippet or not)
        for i in range(len(differences)):
            # Make sure this entry has differences before further processing
            if self.is_empty(differences[i]):
                continue

            # Set some required properties for the snippet to work
            history[i].owner = publicuser
            history[i].slug = recipe.slug + '/history/' + str(
                history[i].key().id())

            # Create the entry
            entry = {
                'recipe': history[i],
                'differences': self.delete_ignored_keys(differences[i]),
                'edited': history[i].created,
                'slug': history[i].slug,
                'show_snippet': False
            }

            # Check if the name or description changed and we should show
            # a snippet
            for snippetItem in RecipeHistoryHandler.SNIPPET_ITEMS:
                if snippetItem in differences[i][2]:
                    entry['show_snippet'] = True
                    # Make sure the color, ibu, and alcohol were created
                    if not hasattr(history[i], 'color'):
                        history[i].update_cache()
                    break

            # Save the entry
            entries.append(entry)

        # Add the final entry only if it's the original recipe, otherwise it
        # will be a version that should have diffs but we didn't generate any.
        if len(history) > 0:
            last = history[-1]
            delta = timedelta(seconds=1)
            if recipe.created - delta < last.created < recipe.created + delta:
                last.owner = publicuser
                last.slug = recipe.slug + '/history/' + str(last.key().id())
                if not hasattr(last, 'color'):
                    last.update_cache()
                entries.append({
                    'recipe': last,
                    'edited': last.created,
                    'slug': last.slug,
                    'customtag': 'Original',
                    'first': True
                })

        # Perform a second pass in reverse to check for large changes that
        # should show up as a snippet but were missed in the pairwise
        # checking above.
        entries[-1]['show_snippet'] = True
        for i in range(len(entries) - 1, 0, -1):
            # Check if the snippet is already showing
            if entries[i]['show_snippet']:
                last_snippet = entries[i]['recipe']
                continue

            # Check if the name, description, color, ibu, or alcohol changed
            # and we should show a snippet
            for snippetItem in RecipeHistoryHandler.IGNORED_KEYS:
                if not hasattr(entries[i]['recipe'], snippetItem):
                    continue

                attr = getattr(entries[i]['recipe'], snippetItem)
                if type(attr) != int and type(attr) != float:
                    continue

                # See if the change was more than 10%, then show the
                # snippet, else show the orb
                try:
                    change = float(attr) / getattr(last_snippet, snippetItem)
                except:
                    change = 2
                logging.info(snippetItem)
                logging.info(change)
                if change < 0.9 or change > 1.1:
                    last_snippet = entries[i]['recipe']
                    entries[i]['show_snippet'] = True
                    break

        # Stop the template from performing another query for the username
        # when it tries to render the recipe
        recipe.owner = publicuser

        self.render('recipe-history.html', {
            'publicuser': publicuser,
            'recipe': recipe,
            'entries': entries
        })
Example #59
0
 def delete_all(self):
     Recipe.objects().delete()
     return None
Example #60
0
        },
        {
            "name": "hltToMash",
            "prettyName": "HLT To Mash",
            "status": con.relay_status(con.settings.relays['hltToMash'])
        },
        {
            "name": "rimsToMash",
            "prettyName": "RIMS To Mash",
            "status": con.relay_status(con.settings.relays["rimsToMash"])
        },
        {
            "name": "pump",
            "prettyName": "Pump",
            "status": con.relay_status(con.settings.relays["pump"])
        }
    ]

    return json.dumps(relays)

# PID API Resource
@app.route("/pid", methods=["GET"])
def pid():
    pid = con.pid_status()
    return json.dumps(pid)


if __name__ == '__main__':
    Recipe.create_table(True)
    app.run('0.0.0.0', 8000, extra_files="static/main.js")