-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Updates📢] CRUD updates with validators in place
- Loading branch information
[esekyi]
committed
Aug 27, 2024
1 parent
948fbb0
commit 6a6960e
Showing
3 changed files
with
171 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,76 @@ | ||
from flask import Blueprint, jsonify, request | ||
from flask import Blueprint, request, url_for, render_template, jsonify, flash, redirect | ||
from app import db | ||
from app.services.recipe_service import get_all_recipes, get_recipe_by_id, create_recipe | ||
from app.services.validation_service import validate_recipe_data | ||
from app.services.category_sevice import get_all_categories | ||
from app.services.image_service import upload_image_to_s3 | ||
from flask_login import login_required, current_user | ||
|
||
bp = Blueprint('recipe_route', __name__) | ||
bp = Blueprint('recipe_routes', __name__) | ||
|
||
|
||
@bp.route('/recipes/create', methods=['GET', 'POST'], strict_slashes=False) | ||
@login_required | ||
def add_recipe(): | ||
if request.method == 'POST': | ||
data = request.form.to_dict() # ensuring form data comes as to dictionary. | ||
ingredients = request.form.getlist('ingredients[]') | ||
comments = request.form.getlist('comments[]') | ||
instructions = request.form.getlist('instructions[]') | ||
image = request.files.get('image') | ||
|
||
errors = validate_recipe_data(data) | ||
if errors: | ||
for error in errors: | ||
flash(error, 'error') | ||
return redirect(url_for('recipe_routes.add_recipe')) | ||
|
||
|
||
image_url = None | ||
if image: | ||
try: | ||
image_url = upload_image_to_s3(image) | ||
except ValueError as e: | ||
flash(str(e), 'danger') | ||
return redirect(url_for('recipe_routes.add_recipe')) | ||
|
||
|
||
try: | ||
send_url = image_url if image_url is not None else '' | ||
create_recipe(data, comments, ingredients, instructions, send_url, user_id=current_user.id) | ||
flash("Recipe created successfully!", 'success') | ||
return redirect(url_for('recipe_routes.list_recipes')) | ||
|
||
except Exception as e: | ||
# Rollback db session in case of an error | ||
db.session.rollback() | ||
flash( | ||
f"An error occurred while creating the recipe: {str(e)}", "error") | ||
return redirect(url_for('recipe_routes.add_recipe')) | ||
|
||
|
||
categories = get_all_categories() | ||
return render_template('recipes/create.html', categories=categories) | ||
|
||
|
||
@bp.route('/recipes', methods=['GET'], strict_slashes=False) | ||
def list_recipes(): | ||
recipes = get_all_recipes() | ||
return render_template('recipes/list.html', recipes=recipes) | ||
|
||
|
||
@bp.route('/recipes/<uuid:recipe_id>', methods=['GET'], strict_slashes=False) | ||
def view_recipe(recipe_id): | ||
pass | ||
|
||
|
||
@bp.route('/recipes/<uuid:recipe_id>/edit', methods=['PUT'], strict_slashes=False) | ||
@login_required | ||
def edit_recipe(recipe_id): | ||
pass | ||
|
||
|
||
@bp.route('/recipes/<uuid:recipe_id>/delete', methods=['DELETE'], strict_slashes=False) | ||
@login_required | ||
def remove_recipe(recipe_id): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
from app.models.recipe import Recipe | ||
from app.models.ingredient import Ingredient | ||
from app.models.comment import Comment | ||
from app.models.instruction import Instruction | ||
from app import db | ||
|
||
|
||
def create_recipe(data, user_id, ingredients, comments, instructions, send_url): | ||
""" | ||
Create a new recipe and save it to the database. | ||
:param data: A dictionary containing recipe data. | ||
:param ingredients: A list of ingredients to associate with the recipe. | ||
:param comments: A list of comments to associate with the recipe. | ||
:param user_id: The ID of the user creating the recipe. | ||
:return: The newly created Recipe object. | ||
""" | ||
try: | ||
new_recipe = Recipe( | ||
title=data['title'], | ||
description=data['description'], | ||
instructions=data['instructions'], | ||
prep_time=int(data.get('prep_time', 0)), # Default to 0 if not provided | ||
cook_time=int(data.get('cook_time', 0)), # Default to 0 if not provided | ||
servings=int(data.get('servings', 0)), # Default to 0 if not provided | ||
category_id=data['category_id'], | ||
user_id=user_id, | ||
image_url=send_url | ||
) | ||
db.session.add(new_recipe) | ||
db.session.flush() # Flush pending transaction to get the recipe ID before committing | ||
|
||
# Handle ingredients | ||
for ingredient_name in ingredients: | ||
if ingredient_name: # not tolerating any empty ingredient | ||
ingredient = Ingredient( | ||
name=ingredient_name, | ||
recipe_id=new_recipe.id | ||
) | ||
db.session.add(ingredient) | ||
|
||
# Handle comments | ||
for comment_text in comments: | ||
if comment_text: # not tolerating empty comments | ||
comment = Comment( | ||
text=comment_text, | ||
user_id=user_id, | ||
recipe_id=new_recipe.id | ||
) | ||
db.session.add(comment) | ||
|
||
# Handle each instruction | ||
for i, instruction in enumerate(instructions): | ||
if instruction: | ||
new_instruction = Instruction( | ||
step_number=i + 1, | ||
name=instruction, | ||
recipe_id=new_recipe.id | ||
) | ||
db.session.add(new_instruction) | ||
|
||
|
||
db.session.commit() # comit all changes to different tables | ||
return new_recipe | ||
|
||
except Exception as e: | ||
db.session.rollback() | ||
raise Exception(f"Failed to create recipe: {str(e)}") | ||
|
||
|
||
def get_all_recipes(): | ||
return Recipe.query.all() | ||
|
||
|
||
def get_recipe_by_id(recipe_id): | ||
return Recipe.query.get(recipe_id) | ||
|
||
|
||
def delete_recipe(recipe): | ||
db.session.delete(recipe) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
def validate_recipe_data(data): | ||
"""validate_recipe_data(data) | ||
validate recipe data as they come in | ||
and display errors if not available | ||
""" | ||
errors = [] | ||
if not data.get('title'): | ||
errors.append('Title is required.') | ||
if not data.get('description'): | ||
errors.append('Description is required.') | ||
if not data.get('instructions'): | ||
errors.append('Instructions are required.') | ||
if not data.get('category_id'): | ||
errors.append('Category is required.') | ||
|
||
return errors | ||
|