Added microservice to download PDFs
This commit is contained in:
35
main.py
35
main.py
@@ -3,8 +3,9 @@ Portfolio Project for CS361 Spring 2022
|
|||||||
Written by Lucas Jensen
|
Written by Lucas Jensen
|
||||||
Last updated 5/12 for Assignment 1
|
Last updated 5/12 for Assignment 1
|
||||||
"""
|
"""
|
||||||
from flask import Flask, redirect, render_template, request
|
from flask import Flask, redirect, render_template, request, send_file
|
||||||
from recipe import Recipe, RecipeBook
|
from recipe import Recipe, RecipeBook
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
book = RecipeBook()
|
book = RecipeBook()
|
||||||
@@ -25,17 +26,39 @@ def recipes_page():
|
|||||||
|
|
||||||
@app.route('/recipes/<_id>', methods=['GET', 'POST'])
|
@app.route('/recipes/<_id>', methods=['GET', 'POST'])
|
||||||
def recipe_page(_id):
|
def recipe_page(_id):
|
||||||
recipe = book.find_by_id(_id)
|
recipe = book.find_by_id(str(_id))
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
scale = request.form.get('scale')
|
if 'scale' in request.form:
|
||||||
new = recipe.scale(scale)
|
scale = request.form.get('scale')
|
||||||
new_id = book.add_recipe(new)
|
new = recipe.scale(scale)
|
||||||
return redirect(f'/recipes/{new_id}')
|
new_id = book.add_recipe(new)
|
||||||
|
return redirect(f'/recipes/{new_id}')
|
||||||
|
|
||||||
|
else:
|
||||||
|
path = write_txt(_id)
|
||||||
|
sleep(0.5)
|
||||||
|
return send_file(path, as_attachment=True)
|
||||||
|
|
||||||
return render_template("recipe.html", content=recipe, _id=_id)
|
return render_template("recipe.html", content=recipe, _id=_id)
|
||||||
|
|
||||||
|
|
||||||
|
def write_txt(_id):
|
||||||
|
"""
|
||||||
|
writes to the txt file to have the microservice make a selected pdf
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
print(_id)
|
||||||
|
with open('recipe.txt', 'w') as txt_file:
|
||||||
|
txt_file.write(_id)
|
||||||
|
|
||||||
|
return f"recipe{_id}.pdf"
|
||||||
|
|
||||||
|
|
||||||
|
# app.route('/recipes/<id>/download')
|
||||||
|
# def
|
||||||
|
|
||||||
|
|
||||||
@app.route('/recipes/<_id>/delete')
|
@app.route('/recipes/<_id>/delete')
|
||||||
def delete_recipe(_id):
|
def delete_recipe(_id):
|
||||||
book.find_and_delete(_id)
|
book.find_and_delete(_id)
|
||||||
|
|||||||
117
pdf-generator.py
Normal file
117
pdf-generator.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
"""
|
||||||
|
Reads a key from a txt file. Searches a json file with the key.
|
||||||
|
Exports the key values in a pdf form. Writes the PDF file name
|
||||||
|
to the txt file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
from fpdf import FPDF
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
TXTFILE = 'recipe.txt' # update to txt file name for read
|
||||||
|
JSONFILE = 'recipes.json' # update to json file name for read
|
||||||
|
CATEGORY = 'recipe' # update category to preceed number in PDF file name
|
||||||
|
|
||||||
|
|
||||||
|
def create_pdf() -> object:
|
||||||
|
"""
|
||||||
|
Create pdf object from FPDF class
|
||||||
|
:return: PDF object
|
||||||
|
"""
|
||||||
|
pdf = FPDF()
|
||||||
|
pdf.add_page()
|
||||||
|
pdf.set_font("Arial", size=15)
|
||||||
|
return pdf
|
||||||
|
|
||||||
|
|
||||||
|
def read_txt(file_name) -> object:
|
||||||
|
"""
|
||||||
|
Open/reads txt file argument
|
||||||
|
:param file_name(str)
|
||||||
|
:return: file content
|
||||||
|
"""
|
||||||
|
with open(file_name, 'r') as txt_file:
|
||||||
|
content = txt_file.read()
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def load_json(file_name) -> object:
|
||||||
|
"""
|
||||||
|
Opens/loads json file argument
|
||||||
|
:param file_name(str)
|
||||||
|
:return: file contentquit
|
||||||
|
"""
|
||||||
|
with open(file_name, 'r') as json_file:
|
||||||
|
content = json.load(json_file)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def add_pdf_content(txt_content, json_content, pdf) -> None:
|
||||||
|
"""
|
||||||
|
Searches json content with key from txt_content. Adds relevant data to pdf object.
|
||||||
|
:param txt_content: txt file content for json search
|
||||||
|
:param json_content: json file content to search
|
||||||
|
:param pdf: pdf object to update
|
||||||
|
:return: none
|
||||||
|
"""
|
||||||
|
for key, value in json_content.items():
|
||||||
|
if key == txt_content:
|
||||||
|
for key, value in value.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
pdf.cell(200, 10, txt=key.title() + ":", ln=1, align='C')
|
||||||
|
for key, value in value.items():
|
||||||
|
pdf.cell(200, 10, txt=key + ": " + str(value), ln=1, align='C')
|
||||||
|
else:
|
||||||
|
pdf.cell(200, 10, txt=key.title() + ": " + str(value), ln=1, align='C')
|
||||||
|
|
||||||
|
|
||||||
|
def generate_pdf(category_name, txt_content, pdf) -> str:
|
||||||
|
"""
|
||||||
|
Generate pdf file from pdf object with relevant naming 'category + key from txt file'
|
||||||
|
:param category_name: category for pdf title
|
||||||
|
:param txt_content: txt identifier for pdf title
|
||||||
|
:param pdf: pdf object to generate pdf file
|
||||||
|
:return: pdf file name
|
||||||
|
"""
|
||||||
|
pdf.output(f"{category_name}{txt_content}.pdf")
|
||||||
|
return f"{category_name}{txt_content}.pdf"
|
||||||
|
|
||||||
|
|
||||||
|
def write_txt(file_name, pdf_file) -> None:
|
||||||
|
"""
|
||||||
|
Write generated pdf file name to txt file
|
||||||
|
:param file_name: txt file(str) to write to
|
||||||
|
:param pdf_file: pdf file name to write(str)
|
||||||
|
:return: none
|
||||||
|
"""
|
||||||
|
with open(file_name, 'w') as txt_file:
|
||||||
|
txt_file.write(pdf_file)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
initial_content = read_txt(TXTFILE) # initialize variables for while loop comparison
|
||||||
|
|
||||||
|
while True:
|
||||||
|
updated_content = read_txt(TXTFILE)
|
||||||
|
# watch for txt change
|
||||||
|
if updated_content != initial_content:
|
||||||
|
if updated_content == 'QUIT': # exit program upon cue
|
||||||
|
break
|
||||||
|
|
||||||
|
pdf = create_pdf() # create pdf object for file generation
|
||||||
|
|
||||||
|
json_content = load_json(JSONFILE) # load json content for data search
|
||||||
|
|
||||||
|
add_pdf_content(updated_content, json_content, pdf) # update pdf object with data
|
||||||
|
|
||||||
|
pdf_file_name = generate_pdf(CATEGORY, updated_content, pdf) # generate pdf file with appropriate name
|
||||||
|
|
||||||
|
write_txt(TXTFILE, pdf_file_name) # write pdf file name to txt file
|
||||||
|
|
||||||
|
initial_content = read_txt(TXTFILE) # update comparison variable
|
||||||
|
|
||||||
|
sleep(.25)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -8,7 +8,7 @@ Last updated 5/12
|
|||||||
import json
|
import json
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
JSON_FILE = "recipes/recipes.json"
|
JSON_FILE = "recipes.json"
|
||||||
|
|
||||||
|
|
||||||
class RecipeBook:
|
class RecipeBook:
|
||||||
|
|||||||
1
recipe.txt
Normal file
1
recipe.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
recipe1.pdf
|
||||||
28
recipes.json
Normal file
28
recipes.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"0": {
|
||||||
|
"quantity": "2",
|
||||||
|
"name": "Sourdough",
|
||||||
|
"ingredients": {
|
||||||
|
"AP Flour": 500,
|
||||||
|
"WW Flour": 500,
|
||||||
|
"Rye Flour": 0,
|
||||||
|
"Water": 0,
|
||||||
|
"Salt": 0,
|
||||||
|
"Yeast": 0,
|
||||||
|
"Starter": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"quantity": "2",
|
||||||
|
"name": "Sourdough * 1.0",
|
||||||
|
"ingredients": {
|
||||||
|
"AP Flour": 500,
|
||||||
|
"WW Flour": 500,
|
||||||
|
"Rye Flour": 0,
|
||||||
|
"Water": 0,
|
||||||
|
"Salt": 0,
|
||||||
|
"Yeast": 0,
|
||||||
|
"Starter": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"0": {
|
|
||||||
"quantity": "2",
|
|
||||||
"name": "Sourdough",
|
|
||||||
"ingredients": {
|
|
||||||
"AP Flour": 500,
|
|
||||||
"WW Flour": 500,
|
|
||||||
"Rye Flour": 0,
|
|
||||||
"Water": 0,
|
|
||||||
"Salt": 0,
|
|
||||||
"Yeast": 0,
|
|
||||||
"Starter": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
python-3.10.0
|
|
||||||
@@ -33,6 +33,9 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<input type="button" onclick="location.href='/recipes/{{_id}}/delete'" value=Delete />
|
<input type="button" onclick="location.href='/recipes/{{_id}}/delete'" value=Delete />
|
||||||
|
<form method="post">
|
||||||
|
<button type="submit">Download</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user