MVP done, along with delete button
This commit is contained in:
28
main.py
28
main.py
@@ -3,8 +3,7 @@ Portfolio Project for CS361 Spring 2022
|
|||||||
Written by Lucas Jensen
|
Written by Lucas Jensen
|
||||||
Last updated 3/29/22 for Assignment 1
|
Last updated 3/29/22 for Assignment 1
|
||||||
"""
|
"""
|
||||||
import json
|
from flask import Flask, redirect, render_template, request
|
||||||
from flask import Flask, redirect, flash, render_template, request, jsonify
|
|
||||||
from markupsafe import escape
|
from markupsafe import escape
|
||||||
|
|
||||||
from recipe import Recipe, RecipeBook, open_json
|
from recipe import Recipe, RecipeBook, open_json
|
||||||
@@ -19,16 +18,25 @@ def home():
|
|||||||
|
|
||||||
@app.route('/recipes', methods=['GET'])
|
@app.route('/recipes', methods=['GET'])
|
||||||
def ReturnJSON():
|
def ReturnJSON():
|
||||||
return render_template("recipe.html", content=open_json())
|
recipes = open_json()
|
||||||
|
if recipes == {}:
|
||||||
|
return render_template("empty.html")
|
||||||
|
return render_template("recipes.html", content=recipes)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/recipes/<_id>', methods=['GET'])
|
@app.route('/recipes/<_id>', methods=['GET'])
|
||||||
def recipe_page(_id):
|
def recipe_page(_id):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# recipe = book.find_by_id(int(_id))
|
recipe = book.find_by_id(_id)
|
||||||
# return jsonify(recipe.get_recipe())
|
|
||||||
recipe = open_json()[_id]
|
return render_template("recipe.html", content=recipe, _id=_id)
|
||||||
return recipe
|
|
||||||
|
|
||||||
|
@app.route('/recipes/<_id>/delete')
|
||||||
|
def delete_recipe(_id):
|
||||||
|
book.delete(_id)
|
||||||
|
|
||||||
|
return redirect("/recipes")
|
||||||
|
|
||||||
|
|
||||||
@app.route('/add', methods=['GET', 'POST'])
|
@app.route('/add', methods=['GET', 'POST'])
|
||||||
@@ -43,16 +51,10 @@ def add_recipe():
|
|||||||
new_recipe = Recipe(name, loaves, flour, water, salt)
|
new_recipe = Recipe(name, loaves, flour, water, salt)
|
||||||
book.add_recipes(new_recipe)
|
book.add_recipes(new_recipe)
|
||||||
|
|
||||||
# flash("Recipe Added!")
|
|
||||||
return redirect("/recipes")
|
return redirect("/recipes")
|
||||||
return render_template("new.html")
|
return render_template("new.html")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# testing
|
|
||||||
# recipes = default_recipes()
|
|
||||||
book = RecipeBook()
|
book = RecipeBook()
|
||||||
# for recipe in recipes:
|
|
||||||
# book.add_recipes(recipe)
|
|
||||||
|
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
|||||||
74
recipe.py
74
recipe.py
@@ -11,8 +11,17 @@ class RecipeBook:
|
|||||||
Represents a recipe book containing several bread recipes
|
Represents a recipe book containing several bread recipes
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._count = 0
|
self._recipes = self.__build_recipes()
|
||||||
self._recipes = {}
|
|
||||||
|
@staticmethod
|
||||||
|
def __build_recipes():
|
||||||
|
"""
|
||||||
|
Builds the recipe book from an existing json file
|
||||||
|
"""
|
||||||
|
with open("recipes/recipes.json", "rt") as f:
|
||||||
|
recipes = json.load(f)
|
||||||
|
|
||||||
|
return recipes
|
||||||
|
|
||||||
def add_recipes(self, recipe: object) -> None:
|
def add_recipes(self, recipe: object) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -21,13 +30,13 @@ class RecipeBook:
|
|||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
keys = open_json()
|
keys = open_json()
|
||||||
for key in keys:
|
count = 0
|
||||||
if int(key) > self._count:
|
|
||||||
self._count = int(key)
|
while str(count) in keys:
|
||||||
self._count += 1
|
count += 1
|
||||||
self._recipes[self._count] = recipe
|
|
||||||
self.save(self._count, recipe)
|
self._recipes[count] = recipe
|
||||||
# self._count += 1
|
self.save(count, recipe)
|
||||||
|
|
||||||
def get_recipes(self) -> list:
|
def get_recipes(self) -> list:
|
||||||
"""
|
"""
|
||||||
@@ -50,15 +59,21 @@ class RecipeBook:
|
|||||||
:param _id: int
|
:param _id: int
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
a_dict = {str(_id): recipe.get_recipe()}
|
self._recipes[_id] = recipe.get_recipe()
|
||||||
|
|
||||||
with open('recipes/recipes.json') as f:
|
with open("recipes/recipes.json", "wt") as f:
|
||||||
data = json.load(f)
|
json.dump(self._recipes, f, indent=4)
|
||||||
|
|
||||||
data.update(a_dict)
|
def delete(self, _id: int) -> None:
|
||||||
|
"""
|
||||||
|
Deletes a recipes as found by its ID
|
||||||
|
:param _id: int: id of the recipe
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
del self._recipes[str(_id)]
|
||||||
|
|
||||||
with open('recipes/recipes.json', 'w') as f:
|
with open("recipes/recipes.json", "wt") as f:
|
||||||
json.dump(data, f)
|
json.dump(self._recipes, f, indent=4)
|
||||||
|
|
||||||
|
|
||||||
class Recipe:
|
class Recipe:
|
||||||
@@ -87,11 +102,12 @@ class Recipe:
|
|||||||
"""
|
"""
|
||||||
recipe_dict = {
|
recipe_dict = {
|
||||||
'quantity': self._num_loaves,
|
'quantity': self._num_loaves,
|
||||||
'name': self._name
|
'name': self._name,
|
||||||
|
'ingredients': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ingredient in self._ingredients:
|
for ingredient in self._ingredients:
|
||||||
recipe_dict[ingredient] = self._ingredients[ingredient]
|
recipe_dict['ingredients'][ingredient] = self._ingredients[ingredient]
|
||||||
|
|
||||||
return recipe_dict
|
return recipe_dict
|
||||||
|
|
||||||
@@ -139,16 +155,6 @@ class Recipe:
|
|||||||
return scaled_recipe
|
return scaled_recipe
|
||||||
|
|
||||||
|
|
||||||
def build_recipe(infile) -> None:
|
|
||||||
"""
|
|
||||||
Builds a recipe object from a JSON file
|
|
||||||
:param infile: filename
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
# TODO
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def default_recipes():
|
def default_recipes():
|
||||||
recipe_1 = Recipe('Country Brown', 1, 600, 300, 13)
|
recipe_1 = Recipe('Country Brown', 1, 600, 300, 13)
|
||||||
recipe_2 = Recipe('Conventional White', 2, 1000, 700, 25)
|
recipe_2 = Recipe('Conventional White', 2, 1000, 700, 25)
|
||||||
@@ -159,8 +165,8 @@ def default_recipes():
|
|||||||
|
|
||||||
def open_json():
|
def open_json():
|
||||||
"""TODO"""
|
"""TODO"""
|
||||||
with open('recipes/recipes.json') as json_file:
|
with open('recipes/recipes.json') as f:
|
||||||
data = json.load(json_file)
|
data = json.load(f)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@@ -171,9 +177,9 @@ if __name__ == "__main__":
|
|||||||
for recipe in recipes:
|
for recipe in recipes:
|
||||||
book.add_recipes(recipe)
|
book.add_recipes(recipe)
|
||||||
|
|
||||||
for recipe in book.get_recipes():
|
# for recipe in book.get_recipes():
|
||||||
print(book.get_recipes()[recipe])
|
# print(book.get_recipes()[recipe])
|
||||||
|
#
|
||||||
rec = Recipe('sandwich loaf', 2, 1000, 700, 25)
|
# rec = Recipe('sandwich loaf', 2, 1000, 700, 25)
|
||||||
rec.add_ingredient('ww flour', 500)
|
# rec.add_ingredient('ww flour', 500)
|
||||||
# rec.save('recipes.json')
|
# rec.save('recipes.json')
|
||||||
|
|||||||
@@ -1 +1,11 @@
|
|||||||
{"0": {"quantity": "1", "name": "bread", "ap_flour": "1", "water": "1", "salt": "1"}, "1": {"quantity": 2, "name": "Conventional White", "ap_flour": 1000, "water": 700, "salt": 25}, "2": {"quantity": 4, "name": "Conventional White * 2.0", "ap_flour": 2000.0, "water": 1400.0, "salt": 50.0}, "3": {"quantity": "1", "name": "sourdough", "ap_flour": "100", "water": "1001", "salt": "1001"}, "4": {"quantity": "11", "name": "milk", "ap_flour": "10101", "water": "10", "salt": "10"}, "5": {"quantity": "1", "name": "white", "ap_flour": "100", "water": "50", "salt": "2"}}
|
{
|
||||||
|
"0": {
|
||||||
|
"quantity": "2",
|
||||||
|
"name": "Sourdough",
|
||||||
|
"ingredients": {
|
||||||
|
"ap_flour": "1000",
|
||||||
|
"water": "600",
|
||||||
|
"salt": "20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
templates/empty.html
Normal file
14
templates/empty.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Recipes{% endblock %}
|
||||||
|
|
||||||
|
{% block html_head %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>Bread Recipes</h1>
|
||||||
|
|
||||||
|
<p>You haven't added any recipes yet!</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -11,18 +11,18 @@
|
|||||||
|
|
||||||
<form action="{{ url_for("add_recipe")}}" method="post">
|
<form action="{{ url_for("add_recipe")}}" method="post">
|
||||||
|
|
||||||
<label for="name">Recipe Name:</label>
|
<label for="name">Recipe Name:</label><br>
|
||||||
<input required type="text" id="name" name="name" placeholder="Sourdough">
|
<input required type="text" id="name" name="name" placeholder="Sourdough">
|
||||||
<br>
|
<br>
|
||||||
<p>Enter all values grams.</p>
|
<p>Enter all values grams.</p>
|
||||||
|
|
||||||
{% for ing in ['flour', 'water', 'salt'] %}
|
{% for ing in ['flour', 'water', 'salt'] %}
|
||||||
<label for="{{ing}}_weight">{{ing.title()}}:</label>
|
<label for="{{ing}}_weight">{{ing.title()}}:</label><br>
|
||||||
<input required type="number" id="{{ing}}_weight" name="{{ing}}_weight" placeholder="100">
|
<input required type="number" id="{{ing}}_weight" name="{{ing}}_weight" placeholder="100"><br>
|
||||||
<br>
|
<br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<label for="yield">Loaves:</label>
|
<label for="yield">Loaves:</label><br>
|
||||||
<input required type="number" id="yield" name="yield" placeholder="2">
|
<input required type="number" id="yield" name="yield" placeholder="2">
|
||||||
|
|
||||||
<button type="submit">Add!</button>
|
<button type="submit">Add!</button>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Recipes{% endblock %}
|
{% block title %}{{content["name"]}}{% endblock %}
|
||||||
|
|
||||||
{% block html_head %}
|
{% block html_head %}
|
||||||
|
|
||||||
@@ -7,13 +7,25 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h1>Bread Recipes</h1>
|
<h1>{{content["name"]}} Recipe</h1>
|
||||||
<ul>
|
|
||||||
{% for recipe in content %}
|
|
||||||
<li>
|
<p>Number of loaves: {{content['quantity']}}</p>
|
||||||
<a href=recipes/{{recipe}}>{{content[recipe]['name']}}</a>
|
|
||||||
</li>
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Ingredient</th>
|
||||||
|
<th>Grams</th>
|
||||||
|
</tr>
|
||||||
|
{% for item in content['ingredients'] %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ item.title() }}</td>
|
||||||
|
<td>{{ content['ingredients'][item] }}</td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</table>
|
||||||
|
|
||||||
|
<input type="button" onclick="location.href='/recipes/{{_id}}/delete'" value=Delete />
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
19
templates/recipes.html
Normal file
19
templates/recipes.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Recipes{% endblock %}
|
||||||
|
|
||||||
|
{% block html_head %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>Bread Recipes</h1>
|
||||||
|
<ul>
|
||||||
|
{% for recipe in content %}
|
||||||
|
<li>
|
||||||
|
<a href=recipes/{{recipe}}>{{content[recipe]['name']}}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user