142 lines
4.7 KiB
Python
142 lines
4.7 KiB
Python
"""Routes for the core tunes table."""
|
|
from flask import Blueprint, jsonify, request
|
|
from app.extensions import db
|
|
from app.models import Tune, TuneByInstrument, TuneNote, Reference, Musician
|
|
from app.auth import require_api_key
|
|
|
|
tunes_bp = Blueprint("tunes", __name__, url_prefix="/tunes")
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# List / filter
|
|
# ---------------------------------------------------------------------------
|
|
@tunes_bp.get("/")
|
|
def list_tunes():
|
|
"""
|
|
Query params (all optional, combinable):
|
|
instrument_id=1
|
|
key=D
|
|
tuning_id=1
|
|
status=callable|review|to_learn
|
|
difficulty=easy|hard
|
|
modal=true|false
|
|
source_id=1
|
|
search=<substring match on name>
|
|
"""
|
|
q = db.session.query(Tune)
|
|
|
|
search = request.args.get("search")
|
|
if search:
|
|
q = q.filter(Tune.name.ilike(f"%{search}%"))
|
|
|
|
key = request.args.get("key")
|
|
if key:
|
|
q = q.filter(Tune.key.ilike(key))
|
|
|
|
modal = request.args.get("modal")
|
|
if modal is not None:
|
|
q = q.filter(Tune.modal == (modal.lower() in ("true", "1", "yes")))
|
|
|
|
source_id = request.args.get("source_id")
|
|
if source_id:
|
|
q = q.filter(Tune.source_id == int(source_id))
|
|
|
|
instrument_id = request.args.get("instrument_id")
|
|
tuning = request.args.get("tuning")
|
|
status = request.args.get("status")
|
|
difficulty = request.args.get("difficulty")
|
|
|
|
if any([instrument_id, tuning, status, difficulty]):
|
|
q = q.join(Tune.instruments)
|
|
if instrument_id:
|
|
q = q.filter(TuneByInstrument.instrument_id == int(instrument_id))
|
|
if tuning:
|
|
q = q.filter(TuneByInstrument.tuning_id == int(tuning))
|
|
if status:
|
|
q = q.filter(TuneByInstrument.status == status)
|
|
if difficulty:
|
|
q = q.filter(TuneByInstrument.difficulty.ilike(difficulty))
|
|
|
|
tunes = q.order_by(Tune.name).all()
|
|
return jsonify([t.to_slim_dict() for t in tunes])
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Get single tune
|
|
# ---------------------------------------------------------------------------
|
|
@tunes_bp.get("/<int:tune_id>")
|
|
def get_tune(tune_id):
|
|
tune = db.get_or_404(Tune, tune_id)
|
|
return jsonify(tune.to_dict())
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Create tune (with optional nested instruments / notes / references)
|
|
# ---------------------------------------------------------------------------
|
|
@tunes_bp.post("/")
|
|
@require_api_key
|
|
def create_tune():
|
|
data = request.get_json(force=True)
|
|
|
|
tune = Tune(
|
|
name=data.get("name"),
|
|
key=data.get("key"),
|
|
modal=data.get("modal"),
|
|
source_id=data.get("source_id"),
|
|
)
|
|
db.session.add(tune)
|
|
db.session.flush()
|
|
|
|
for inst_data in data.get("instruments", []):
|
|
entry = TuneByInstrument(
|
|
tune_id=tune.id,
|
|
instrument_id=inst_data["instrument_id"],
|
|
learned_from_id=inst_data.get("learned_from_id"),
|
|
tuning_id=inst_data.get("tuning_id"),
|
|
date_learned=inst_data.get("date_learned"),
|
|
status=inst_data.get("status"),
|
|
difficulty=inst_data.get("difficulty"),
|
|
)
|
|
db.session.add(entry)
|
|
|
|
for note_data in data.get("notes", []):
|
|
db.session.add(TuneNote(tune_id=tune.id, note=note_data.get("note")))
|
|
|
|
for ref_data in data.get("references", []):
|
|
ref = Reference(tune_id=tune.id, link=ref_data.get("link"), site=ref_data.get("site"))
|
|
db.session.add(ref)
|
|
db.session.flush()
|
|
for m in ref_data.get("musicians", []):
|
|
musician = db.session.get(Musician, m["id"])
|
|
if musician:
|
|
ref.musicians.append(musician)
|
|
|
|
db.session.commit()
|
|
return jsonify(tune.to_dict()), 201
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Update tune core fields
|
|
# ---------------------------------------------------------------------------
|
|
@tunes_bp.patch("/<int:tune_id>")
|
|
@require_api_key
|
|
def update_tune(tune_id):
|
|
tune = db.get_or_404(Tune, tune_id)
|
|
data = request.get_json(force=True)
|
|
for field in ("name", "key", "modal", "source_id"):
|
|
if field in data:
|
|
setattr(tune, field, data[field])
|
|
db.session.commit()
|
|
return jsonify(tune.to_dict())
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Delete tune
|
|
# ---------------------------------------------------------------------------
|
|
@tunes_bp.delete("/<int:tune_id>")
|
|
@require_api_key
|
|
def delete_tune(tune_id):
|
|
tune = db.get_or_404(Tune, tune_id)
|
|
db.session.delete(tune)
|
|
db.session.commit()
|
|
return jsonify({"deleted": tune_id})
|