1
This commit is contained in:
135
backend/app/routes/recipe_routes.py
Normal file
135
backend/app/routes/recipe_routes.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from flask import Blueprint, current_app, request
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
from app.extensions import db
|
||||
from app.models import Recipe
|
||||
from app.utils.auth import admin_required
|
||||
from app.utils.response import fail, ok
|
||||
|
||||
|
||||
recipe_bp = Blueprint("recipe", __name__)
|
||||
|
||||
|
||||
def _recipe_payload(recipe: Recipe, payload: dict) -> None:
|
||||
recipe.name = payload.get("name", recipe.name)
|
||||
recipe.category = payload.get("category", recipe.category or "轻食")
|
||||
recipe.description = payload.get("description", recipe.description or "")
|
||||
recipe.calories = float(payload.get("calories", recipe.calories or 0))
|
||||
recipe.protein = float(payload.get("protein", recipe.protein or 0))
|
||||
recipe.fat = float(payload.get("fat", recipe.fat or 0))
|
||||
recipe.carbs = float(payload.get("carbs", recipe.carbs or 0))
|
||||
recipe.fiber = float(payload.get("fiber", recipe.fiber or 0))
|
||||
recipe.tags = payload.get("tags", recipe.tags or [])
|
||||
recipe.difficulty = payload.get("difficulty", recipe.difficulty or "easy")
|
||||
|
||||
|
||||
@recipe_bp.get("")
|
||||
@jwt_required(optional=True)
|
||||
def list_recipes():
|
||||
keyword = (request.args.get("keyword") or "").strip()
|
||||
category = (request.args.get("category") or "").strip()
|
||||
page = max(int(request.args.get("page", 1) or 1), 1)
|
||||
page_size = min(max(int(request.args.get("page_size", 10) or 10), 1), 50)
|
||||
|
||||
query = Recipe.query
|
||||
if keyword:
|
||||
query = query.filter(Recipe.name.like(f"%{keyword}%"))
|
||||
if category:
|
||||
query = query.filter(Recipe.category == category)
|
||||
|
||||
pagination = query.order_by(Recipe.id.desc()).paginate(page=page, per_page=page_size, error_out=False)
|
||||
data = {
|
||||
"items": [item.to_dict() for item in pagination.items],
|
||||
"total": pagination.total,
|
||||
"page": page,
|
||||
"page_size": page_size,
|
||||
}
|
||||
return ok(data)
|
||||
|
||||
|
||||
@recipe_bp.get("/<int:recipe_id>")
|
||||
@jwt_required(optional=True)
|
||||
def get_recipe(recipe_id: int):
|
||||
recipe = Recipe.query.get(recipe_id)
|
||||
if not recipe:
|
||||
return fail("食谱不存在", 404)
|
||||
return ok(recipe.to_dict())
|
||||
|
||||
|
||||
@recipe_bp.post("")
|
||||
@admin_required
|
||||
def create_recipe():
|
||||
payload = request.get_json(silent=True) or {}
|
||||
if not payload.get("name"):
|
||||
return fail("缺少食谱名称", 400)
|
||||
|
||||
recipe = Recipe()
|
||||
_recipe_payload(recipe, payload)
|
||||
|
||||
db.session.add(recipe)
|
||||
db.session.commit()
|
||||
return ok(recipe.to_dict(), "食谱创建成功")
|
||||
|
||||
|
||||
@recipe_bp.put("/<int:recipe_id>")
|
||||
@admin_required
|
||||
def update_recipe(recipe_id: int):
|
||||
recipe = Recipe.query.get(recipe_id)
|
||||
if not recipe:
|
||||
return fail("食谱不存在", 404)
|
||||
|
||||
payload = request.get_json(silent=True) or {}
|
||||
_recipe_payload(recipe, payload)
|
||||
db.session.commit()
|
||||
return ok(recipe.to_dict(), "食谱更新成功")
|
||||
|
||||
|
||||
@recipe_bp.delete("/<int:recipe_id>")
|
||||
@admin_required
|
||||
def delete_recipe(recipe_id: int):
|
||||
recipe = Recipe.query.get(recipe_id)
|
||||
if not recipe:
|
||||
return fail("食谱不存在", 404)
|
||||
|
||||
db.session.delete(recipe)
|
||||
db.session.commit()
|
||||
return ok({}, "食谱删除成功")
|
||||
|
||||
|
||||
@recipe_bp.post("/import")
|
||||
@admin_required
|
||||
def import_recipes():
|
||||
payload = request.get_json(silent=True) or {}
|
||||
rows = payload.get("items")
|
||||
|
||||
if not isinstance(rows, list):
|
||||
seed_file = Path(current_app.root_path).parents[0] / "seed" / "recipes_seed.json"
|
||||
if seed_file.exists():
|
||||
with seed_file.open("r", encoding="utf-8-sig") as file:
|
||||
rows = json.load(file)
|
||||
else:
|
||||
return fail("导入数据为空,且未找到默认种子文件", 400)
|
||||
|
||||
created_count = 0
|
||||
updated_count = 0
|
||||
|
||||
for item in rows:
|
||||
name = (item.get("name") or "").strip()
|
||||
if not name:
|
||||
continue
|
||||
|
||||
recipe = Recipe.query.filter_by(name=name).first()
|
||||
if recipe:
|
||||
_recipe_payload(recipe, item)
|
||||
updated_count += 1
|
||||
else:
|
||||
recipe = Recipe()
|
||||
_recipe_payload(recipe, item)
|
||||
db.session.add(recipe)
|
||||
created_count += 1
|
||||
|
||||
db.session.commit()
|
||||
return ok({"created": created_count, "updated": updated_count}, "食谱导入完成")
|
||||
Reference in New Issue
Block a user