Add term column

This commit is contained in:
Ian Keane 2026-06-11 17:28:07 -04:00
parent b5e2e8ab2a
commit 377462ed20
5 changed files with 100 additions and 1 deletions

View file

@ -10,6 +10,7 @@ from app.routes_sources import sources_bp
from app.routes_musicians import musicians_bp
from app.routes_tunings import tunings_bp
from app.routes_reference_sites import reference_sites_bp
from app.routes_terms import terms_bp
def create_app():
@ -39,6 +40,7 @@ def create_app():
app.register_blueprint(musicians_bp)
app.register_blueprint(tunings_bp)
app.register_blueprint(reference_sites_bp)
app.register_blueprint(terms_bp)
# --- Error handlers ---
from sqlalchemy.exc import IntegrityError

View file

@ -61,6 +61,18 @@ class Tuning(db.Model):
return {"id": self.id, "name": self.name}
class Term(db.Model):
__tablename__ = "terms"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=False, unique=True)
entries = db.relationship("TuneByInstrument", back_populates="term")
def to_dict(self):
return {"id": self.id, "name": self.name}
class Tune(db.Model):
__tablename__ = "tunes"
@ -114,6 +126,7 @@ class TuneByInstrument(db.Model):
instrument_id = Column(Integer, ForeignKey("instruments.id", ondelete="CASCADE"), nullable=False)
learned_from_id = Column(Integer, ForeignKey("musicians.id", ondelete="SET NULL"), nullable=True)
tuning_id = Column(Integer, ForeignKey("tunings.id", ondelete="SET NULL"), nullable=True)
term_id = Column(Integer, ForeignKey("terms.id", ondelete="SET NULL"), nullable=True)
date_learned = Column(Date, nullable=True)
status = Column(String, nullable=True)
difficulty = Column(String, nullable=True)
@ -121,6 +134,7 @@ class TuneByInstrument(db.Model):
tune = db.relationship("Tune", back_populates="instruments")
instrument = db.relationship("Instrument", back_populates="entries")
tuning = db.relationship("Tuning", back_populates="entries")
term = db.relationship("Term", back_populates="entries")
learned_from_musician = db.relationship("Musician", back_populates="instrument_entries")
notes = db.relationship("TuneByInstrumentNote", back_populates="entry", cascade="all, delete-orphan")
@ -135,6 +149,8 @@ class TuneByInstrument(db.Model):
"date_learned": self.date_learned.isoformat() if self.date_learned else None,
"tuning_id": self.tuning_id,
"tuning": self.tuning.name if self.tuning else None,
"term_id": self.term_id,
"term": self.term.name if self.term else None,
"status": self.status,
"difficulty": self.difficulty,
"notes": [n.to_dict() for n in self.notes],
@ -151,6 +167,8 @@ class TuneByInstrument(db.Model):
"date_learned": self.date_learned.isoformat() if self.date_learned else None,
"tuning_id": self.tuning_id,
"tuning": self.tuning.name if self.tuning else None,
"term_id": self.term_id,
"term": self.term.name if self.term else None,
"status": self.status,
"difficulty": self.difficulty,
}

View file

@ -77,6 +77,7 @@ def create_tune_instrument(tune_id):
instrument_id=instrument_id,
learned_from_id=data.get("learned_from_id"),
tuning_id=data.get("tuning_id"),
term_id=data.get("term_id"),
date_learned=data.get("date_learned"),
status=data.get("status"),
difficulty=data.get("difficulty"),
@ -94,7 +95,7 @@ def create_tune_instrument(tune_id):
def update_tune_instrument(tune_id, entry_id):
entry = db.get_or_404(TuneByInstrument, entry_id)
data = request.get_json(force=True)
fields = ("instrument_id", "learned_from_id", "tuning_id", "date_learned",
fields = ("instrument_id", "learned_from_id", "tuning_id", "term_id", "date_learned",
"status", "difficulty")
for field in fields:
if field in data:

43
app/routes_terms.py Normal file
View file

@ -0,0 +1,43 @@
"""Routes for terms lookup table."""
from flask import Blueprint, jsonify, request
from app.extensions import db
from app.models import Term
from app.auth import require_api_key
terms_bp = Blueprint("terms", __name__, url_prefix="/terms")
@terms_bp.get("/")
def list_terms():
terms = db.session.query(Term).order_by(Term.name).all()
return jsonify([t.to_dict() for t in terms])
@terms_bp.post("/")
@require_api_key
def create_term():
data = request.get_json(force=True)
term = Term(name=data["name"])
db.session.add(term)
db.session.commit()
return jsonify(term.to_dict()), 201
@terms_bp.patch("/<int:term_id>")
@require_api_key
def update_term(term_id):
term = db.get_or_404(Term, term_id)
data = request.get_json(force=True)
if "name" in data:
term.name = data["name"]
db.session.commit()
return jsonify(term.to_dict())
@terms_bp.delete("/<int:term_id>")
@require_api_key
def delete_term(term_id):
term = db.get_or_404(Term, term_id)
db.session.delete(term)
db.session.commit()
return jsonify({"deleted": term_id})

View file

@ -0,0 +1,35 @@
"""add terms table and term_id to tune_by_instrument
Revision ID: b1c2d3e4f5a6
Revises: f1a2b3c4d5e6
Create Date: 2026-06-09
"""
from alembic import op
import sqlalchemy as sa
revision = "b1c2d3e4f5a6"
down_revision = "f1a2b3c4d5e6"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table(
"terms",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("name", sa.String(), nullable=False, unique=True),
)
op.add_column(
"tune_by_instrument",
sa.Column(
"term_id",
sa.Integer(),
sa.ForeignKey("terms.id", ondelete="SET NULL"),
nullable=True,
),
)
def downgrade() -> None:
op.drop_column("tune_by_instrument", "term_id")
op.drop_table("terms")