commit 04dbe6c309b189348a559f092089b403e016700e Author: arhetip Date: Tue Jan 31 23:43:08 2023 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9010220 --- /dev/null +++ b/.gitignore @@ -0,0 +1,428 @@ +# Created by https://www.toptal.com/developers/gitignore/api/python,flask,vim,visualstudiocode,pycharm +# Edit at https://www.toptal.com/developers/gitignore?templates=python,flask,vim,visualstudiocode,pycharm + +### Flask ### +instance/* +!instance/.gitignore +.webassets-cache +.env + +### Flask.Python Stack ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Python ### +# Byte-compiled / optimized / DLL files + +# C extensions + +# Distribution / packaging + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. + +# Installer logs + +# Unit test / coverage reports + +# Translations + +# Django stuff: + +# Flask stuff: + +# Scrapy stuff: + +# Sphinx documentation + +# PyBuilder + +# Jupyter Notebook + +# IPython + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm + +# Celery stuff + +# SageMath parsed files + +# Environments + +# Spyder project settings + +# Rope project settings + +# mkdocs documentation + +# mypy + +# Pyre type checker + +# pytype static type analyzer + +# Cython debug symbols + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope +.vscode/*.code-snippets + +# Ignore code-workspaces +*.code-workspace + +# End of https://www.toptal.com/developers/gitignore/api/python,flask,vim,visualstudiocode,pycharm + +### venv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json +*.db + +.idea diff --git a/kuhkal/__init__.py b/kuhkal/__init__.py new file mode 100644 index 0000000..cdda51a --- /dev/null +++ b/kuhkal/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask +from flask_sqlalchemy import SQLAlchemy + +app = Flask(__name__) +app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///kuhinja.db" +app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False + +db = SQLAlchemy(app) + +from . import routes + diff --git a/kuhkal/models.py b/kuhkal/models.py new file mode 100644 index 0000000..4a53871 --- /dev/null +++ b/kuhkal/models.py @@ -0,0 +1,26 @@ +from . import db + +class RecipeIngredientAssoc(db.Model): + __tablename__ = "RecipeIngredientAssoc" + recipe_id = db.Column(db.Integer, db.ForeignKey("recipe.id"), primary_key=True) + ingredient_id = db.Column( + db.Integer, db.ForeignKey("ingredient.id"), primary_key=True + ) + ingredient_ammount = db.Column(db.Numeric(10, 2)) + ingredients = db.relationship("Ingredient", back_populates="recipe") + recipe = db.relationship("Recipe", back_populates="ingredients") + + +class Recipe(db.Model): + __tablename__ = "recipe" + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(120), unique=True, nullable=False) + ingredients = db.relationship("RecipeIngredientAssoc", back_populates="recipe") + + +class Ingredient(db.Model): + __tablename__ = "ingredient" + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(120), unique=True, nullable=False) + price = db.Column(db.Numeric(10, 2)) + recipe = db.relationship("RecipeIngredientAssoc", back_populates="ingredients") diff --git a/kuhkal/routes.py b/kuhkal/routes.py new file mode 100644 index 0000000..2e0edfa --- /dev/null +++ b/kuhkal/routes.py @@ -0,0 +1,206 @@ +from flask import render_template, request, redirect, jsonify + +from . import app +from .models import Recipe, Ingredient, RecipeIngredientAssoc +from . import db +from .utils import get_all_recipes + + +@app.get("/") +def index(): + data = {"recipes": get_all_recipes()} + return render_template("pages/index.html", data=data) + + +@app.route("/ingredients") +@app.route("/sastojci") +def show_ingredients(): + ingredients = db.session.query(Ingredient).all() + data = {"ingredients": ingredients} + return render_template("pages/ingredients.html", data=data) + + +@app.get("/ingredients/new") +def show_new_ingredient_form(): + return render_template("pages/add_ingredient.html") + + +@app.post("/ingredients/new") +def add_new_ingredient(): + name = request.form["name"] + price = request.form["price"] + ingredient = Ingredient(name=name, price=price) + try: + db.session.add(ingredient) + db.session.commit() + except Exception as e: + return "greska, vec postoji sastojak" + + return "napravljeno" + + +@app.get("/ingredients/edit/") +def show_edit_ingredient_form(id): + ingredient = Ingredient.query.get(id) + return render_template("pages/edit_ingredient.html", ingredient=ingredient) + + +@app.post("/ingredients/edit/") +def edit_ingredient(id): + old_ingredient = Ingredient.query.get(id) + name = request.form["name"] + price = request.form["price"] + if old_ingredient.name != name: + old_ingredient.name = name + if old_ingredient.price != price: + old_ingredient.price = price + + db.session.flush() + db.session.commit() + return "updated" + + +@app.get("/ingredients/delete/") +def delete_ingredient(id): + Ingredient.query.filter_by(id=id).delete() + db.session.commit() + return "Deleted" + + +# Recipes CRUD +@app.get("/recipes/") +def show_recipe(id: int): + recipe = Recipe.query.get(id) + ingredients = [] + for ingredient in recipe.ingredients: + ingr = Ingredient.query.get(ingredient.ingredient_id) + ingr_dict = { + "name": ingr.name, + "price": ingr.price, + "ammount": ingredient.ingredient_ammount, + } + ingredients.append(ingr_dict) + data = {"recipe": recipe, "ingredients": ingredients} + return render_template("pages/show_recipe.html", data=data) + + +@app.get("/recipes/new") +def create_recipe(): + ingredients = Ingredient.query.all() + data = {"ingredients": ingredients} + return render_template("pages/create_recipe.html", data=data) + + +@app.post("/recipes/new") +def create_recipe_in_db(): + recipe = Recipe(name=request.form["recipe_name"]) + ingredient_ids = list(map(int, request.form.getlist("ingredients"))) + ingredients = map(Ingredient.query.get, ingredient_ids) + for ing in ingredients: + assoc = RecipeIngredientAssoc() + assoc.ingredient = ing + assoc.ingredient_id = ing.id + assoc.ingredient_name = ing.name + assoc.ingredient_price = ing.price + assoc.recipe = recipe + assoc.recipe_id = recipe.id + ammount = float(request.form[f"{ing.id}_ammount"]) + assoc.ingredient_ammount = ammount + db.session.add(recipe) + db.session.commit() + return "created" + + +@app.get("/recipes/edit/") +def edit_recipe_form(id): + recipe = Recipe.query.get(id) + ingredients_inside = [] + for ingredient in recipe.ingredients: + ingr = Ingredient.query.get(ingredient.ingredient_id) + ingr_dict = { + "name": ingr.name, + "price": ingr.price, + "ammount": ingredient.ingredient_ammount, + "id": ingr.id, + } + ingredients_inside.append(ingr_dict) + all_ingredients = Ingredient.query.all() + ingredients_rest = [ + ingr for ingr in all_ingredients if ingr not in ingredients_inside + ] + data = { + "recipe": recipe, + "ingredients_inside": ingredients_inside, + "ingredients_rest": ingredients_rest, + } + return render_template("pages/edit_recipe.html", data=data) + + +@app.post("/recipes/edit/") +def edit_recipe_in_db(id): + old_recipe = Recipe.query.get(id) + ingredient_ids = list(map(int, request.form.getlist("ingredients"))) + ingredients = map(Ingredient.query.get, ingredient_ids) + ingredient_inside_ids = [] + + for assoc in old_recipe.ingredients: + ingredient_inside_ids.append(assoc.ingredient_id) + if assoc.ingredient_id in ingredient_ids: + ammount = int(request.form[f"{assoc.ingredient_id}_ammount"]) + assoc.ingredient_ammount = ammount + db.session.add(assoc) + + for ing_id in ingredient_ids: + if ing_id not in ingredient_inside_ids: + assoc = RecipeIngredientAssoc() + ing = Ingredient.query.get(ing_id) + assoc.ingredient = ing + assoc.ingredient_id = ing.id + assoc.ingredient_name = ing.name + assoc.ingredient_price = ing.price + assoc.recipe = old_recipe + assoc.recipe_id = old_recipe.id + ammount = int(request.form[f"{ing.id}_ammount"]) + assoc.ingredient_ammount = ammount + + db.session.add(old_recipe) + db.session.commit() + return "ok" + + +@app.get("/calculate") +def calculator(): + data = {"recipes": Recipe.query.all()} + return render_template("pages/calculate.html", data=data) + + +@app.post("/calculate") +def calculate(): + req_data = request.get_json() + recipe_id = req_data["recipe_id"] + recipe = Recipe.query.get(recipe_id) + ingredients_inside = [] + ammount = req_data["ammount"] + for ingredient in recipe.ingredients: + ingr = Ingredient.query.get(ingredient.ingredient_id) + ingr_dict = { + "name": ingr.name, + "price": ingr.price, + "ammount": ingredient.ingredient_ammount, + "calculated_ammount": float(ingredient.ingredient_ammount) + * (int(ammount) / 10), + "calculated_price": float(ingr.price) * (int(ammount) / 10), + "id": ingr.id, + } + ingredients_inside.append(ingr_dict) + price = calculate_price(ingredients_inside) + data = {"ingredients": ingredients_inside, "price": price} + + return jsonify(data) + + +def calculate_price(ingredients: list) -> float: + price = 0 + for ingredient in ingredients: + price += ingredient["calculated_price"] + return price diff --git a/kuhkal/templates/includes/calculate_form.html b/kuhkal/templates/includes/calculate_form.html new file mode 100644 index 0000000..b51d166 --- /dev/null +++ b/kuhkal/templates/includes/calculate_form.html @@ -0,0 +1,9 @@ +
+ + + +
diff --git a/kuhkal/templates/includes/calculate_results.html b/kuhkal/templates/includes/calculate_results.html new file mode 100644 index 0000000..1355a89 --- /dev/null +++ b/kuhkal/templates/includes/calculate_results.html @@ -0,0 +1,18 @@ +
+ + + + + + + + +
SastojakKolicinaCena
+

Cena: RSD

+
diff --git a/kuhkal/templates/includes/edit_ingredient_form.html b/kuhkal/templates/includes/edit_ingredient_form.html new file mode 100644 index 0000000..627e939 --- /dev/null +++ b/kuhkal/templates/includes/edit_ingredient_form.html @@ -0,0 +1,11 @@ +
+ + +
+ + +
+ +
diff --git a/kuhkal/templates/includes/edit_recipe_form.html b/kuhkal/templates/includes/edit_recipe_form.html new file mode 100644 index 0000000..0db4c29 --- /dev/null +++ b/kuhkal/templates/includes/edit_recipe_form.html @@ -0,0 +1,15 @@ +
+ + +
+ {% for ingredient in data["ingredients_inside"] %} + +
+ {% endfor %} +
+ {% for ingredient in data["ingredients_rest"] %} + +
+ {% endfor %} + +
diff --git a/kuhkal/templates/includes/footer.html b/kuhkal/templates/includes/footer.html new file mode 100644 index 0000000..a9b3bf6 --- /dev/null +++ b/kuhkal/templates/includes/footer.html @@ -0,0 +1,3 @@ +
+
+
diff --git a/kuhkal/templates/includes/header.html b/kuhkal/templates/includes/header.html new file mode 100644 index 0000000..a5c5d26 --- /dev/null +++ b/kuhkal/templates/includes/header.html @@ -0,0 +1,13 @@ + diff --git a/kuhkal/templates/includes/new_ingredient_form.html b/kuhkal/templates/includes/new_ingredient_form.html new file mode 100644 index 0000000..d5f3985 --- /dev/null +++ b/kuhkal/templates/includes/new_ingredient_form.html @@ -0,0 +1,11 @@ +
+ + +
+ + +
+ +
diff --git a/kuhkal/templates/includes/new_recipe_form.html b/kuhkal/templates/includes/new_recipe_form.html new file mode 100644 index 0000000..f988c54 --- /dev/null +++ b/kuhkal/templates/includes/new_recipe_form.html @@ -0,0 +1,10 @@ +
+ + +
+ {% for ingredient in data["ingredients"] %} + +
+ {% endfor %} + +
diff --git a/kuhkal/templates/layouts/base.html b/kuhkal/templates/layouts/base.html new file mode 100644 index 0000000..aad0dff --- /dev/null +++ b/kuhkal/templates/layouts/base.html @@ -0,0 +1,17 @@ + + + + + + + Kuhinja Kalkulator + + +
+ {% include "includes/header.html" %} + {% block content %} + {% endblock content %} + {% include "includes/footer.html" %} +
+ + diff --git a/kuhkal/templates/pages/add_ingredient.html b/kuhkal/templates/pages/add_ingredient.html new file mode 100644 index 0000000..44413ed --- /dev/null +++ b/kuhkal/templates/pages/add_ingredient.html @@ -0,0 +1,4 @@ +{% extends "layouts/base.html" %} +{% block content %} + {% include "includes/new_ingredient_form.html" %} +{% endblock %} diff --git a/kuhkal/templates/pages/calculate.html b/kuhkal/templates/pages/calculate.html new file mode 100644 index 0000000..a2acf53 --- /dev/null +++ b/kuhkal/templates/pages/calculate.html @@ -0,0 +1,24 @@ +{% extends "layouts/base.html" %} + +{% block content %} +
+ {% include "includes/calculate_form.html" %} + {% include "includes/calculate_results.html" %} +
+{% endblock content %} diff --git a/kuhkal/templates/pages/create_recipe.html b/kuhkal/templates/pages/create_recipe.html new file mode 100644 index 0000000..97ea276 --- /dev/null +++ b/kuhkal/templates/pages/create_recipe.html @@ -0,0 +1,4 @@ +{% extends "layouts/base.html" %} +{% block content %} + {% include "includes/new_recipe_form.html" %} +{% endblock content %} diff --git a/kuhkal/templates/pages/edit_ingredient.html b/kuhkal/templates/pages/edit_ingredient.html new file mode 100644 index 0000000..9cf3c65 --- /dev/null +++ b/kuhkal/templates/pages/edit_ingredient.html @@ -0,0 +1,4 @@ +{% extends "layouts/base.html" %} +{% block content %} + {% include "includes/edit_ingredient_form.html" %} +{% endblock %} diff --git a/kuhkal/templates/pages/edit_recipe.html b/kuhkal/templates/pages/edit_recipe.html new file mode 100644 index 0000000..9979076 --- /dev/null +++ b/kuhkal/templates/pages/edit_recipe.html @@ -0,0 +1,4 @@ +{% extends "layouts/base.html" %} +{% block content %} + {% include "includes/edit_recipe_form.html" %} +{% endblock content %} diff --git a/kuhkal/templates/pages/index.html b/kuhkal/templates/pages/index.html new file mode 100644 index 0000000..d65705d --- /dev/null +++ b/kuhkal/templates/pages/index.html @@ -0,0 +1,27 @@ +{% extends "layouts/base.html" %} + +{% block content %} +
+ {% for recipe in data["recipes"] %} +
  • +

    {{recipe.recipe.name}}

    + + + + + + + + + {% for i in recipe.ingredients %} + + + + + + {% endfor %} +
    SastojakKolicinaCena
    {{ i.name }} {{ i.ammount }}{{ i.price }}
    +
  • + {% endfor %} +
    +{% endblock content %} diff --git a/kuhkal/templates/pages/ingredients.html b/kuhkal/templates/pages/ingredients.html new file mode 100644 index 0000000..69fbdb6 --- /dev/null +++ b/kuhkal/templates/pages/ingredients.html @@ -0,0 +1,19 @@ +{% extends "layouts/base.html" %} +{% block content %} + Dodaj sastojak + + + + + + + {% for ingredient in data["ingredients"] %} + + + + + + + {% endfor %} +
    NazivCenaAkcije
    {{ingredient.name}}{{ingredient.price}} RSDIzmeniObrisi
    +{% endblock content %} diff --git a/kuhkal/templates/pages/show_recipe.html b/kuhkal/templates/pages/show_recipe.html new file mode 100644 index 0000000..a231c75 --- /dev/null +++ b/kuhkal/templates/pages/show_recipe.html @@ -0,0 +1,10 @@ +{% extends "layouts/base.html" %} + +{% block content %} +

    {{data["recipe"].name}}

    +
      + {% for ingredient in data["ingredients"] %} +
    • {{ingredient.name}}
    • + {% endfor %} +
    +{% endblock content %} diff --git a/kuhkal/utils.py b/kuhkal/utils.py new file mode 100644 index 0000000..e73fc87 --- /dev/null +++ b/kuhkal/utils.py @@ -0,0 +1,19 @@ +from .models import Recipe, Ingredient +import typing as t +from . import db + +def get_all_recipes() -> t.List: + recipes = db.session.query(Recipe).all() + all_recipes = [] + for recipe in recipes: + ingredients = [] + for ingredient in recipe.ingredients: + ingr = Ingredient.query.get(ingredient.ingredient_id) + ingr_dict = { + "name": ingr.name, + "price": ingr.price, + "ammount": ingredient.ingredient_ammount, + } + ingredients.append(ingr_dict) + all_recipes.append({"recipe": recipe, "ingredients": ingredients}) + return all_recipes diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..43373ae --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +flask +Flask-SQLAlchemy +black +bandit diff --git a/run.py b/run.py new file mode 100644 index 0000000..5e477f5 --- /dev/null +++ b/run.py @@ -0,0 +1,4 @@ +from kuhkal import app + +if __name__ == "__main__": + app.run() diff --git a/test_db.py b/test_db.py new file mode 100644 index 0000000..6ed6549 --- /dev/null +++ b/test_db.py @@ -0,0 +1,31 @@ +from kuhkal import models +from kuhkal import db + +def main(): + db.create_all() + recipe = models.Recipe(name="Pasulj") + ing_1 = models.Ingredient(name="Meso", price=30) + ing_2 = models.Ingredient(name="Luk", price=38) + db.session.add(ing_1) + db.session.add(ing_2) + db.session.commit() + ingredients = [ing_2, ing_1] + for ing in ingredients: + assoc = models.RecipeIngredientAssoc() + assoc.ingredient = ing + assoc.ingredient_id = ing.id + assoc.ingredient_name= ing.name + assoc.ingredient_price= ing.price + assoc.recipe = recipe + assoc.recipe_id = recipe.id + assoc.ingredient_ammount = 30 + for ing in recipe.ingredients: + print(ing.ingredient.name) + db.session.add(recipe) + db.session.commit() + + +if __name__ == "__main__": + main() + +