176 lines
7.1 KiB
Python
176 lines
7.1 KiB
Python
|
|
from sqlalchemy import Boolean, Column, Date, ForeignKey, Integer, String, Table, UniqueConstraint
|
||
|
|
from app.extensions import db
|
||
|
|
|
||
|
|
|
||
|
|
# ── Many-to-many: references ↔ musicians ─────────────────────
|
||
|
|
reference_musicians = Table(
|
||
|
|
"reference_musicians",
|
||
|
|
db.metadata,
|
||
|
|
Column("reference_id", Integer, ForeignKey("references.id", ondelete="CASCADE"), primary_key=True),
|
||
|
|
Column("musician_id", Integer, ForeignKey("musicians.id", ondelete="CASCADE"), primary_key=True),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class Musician(db.Model):
|
||
|
|
__tablename__ = "musicians"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
name = Column(String, nullable=False)
|
||
|
|
|
||
|
|
references = db.relationship("Reference", secondary=reference_musicians, back_populates="musicians")
|
||
|
|
instrument_entries = db.relationship("TuneByInstrument", back_populates="learned_from_musician")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {"id": self.id, "name": self.name}
|
||
|
|
|
||
|
|
|
||
|
|
class Source(db.Model):
|
||
|
|
__tablename__ = "sources"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
name = Column(String, nullable=False)
|
||
|
|
|
||
|
|
tunes = db.relationship("Tune", back_populates="source")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {"id": self.id, "name": self.name}
|
||
|
|
|
||
|
|
|
||
|
|
class Instrument(db.Model):
|
||
|
|
__tablename__ = "instruments"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
name = Column(String, nullable=False, unique=True)
|
||
|
|
|
||
|
|
entries = db.relationship("TuneByInstrument", back_populates="instrument")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {"id": self.id, "name": self.name}
|
||
|
|
|
||
|
|
|
||
|
|
class Tuning(db.Model):
|
||
|
|
__tablename__ = "tunings"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
name = Column(String, nullable=False, unique=True)
|
||
|
|
|
||
|
|
entries = db.relationship("TuneByInstrument", back_populates="tuning")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {"id": self.id, "name": self.name}
|
||
|
|
|
||
|
|
|
||
|
|
class Tune(db.Model):
|
||
|
|
__tablename__ = "tunes"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
name = Column(String, nullable=True)
|
||
|
|
key = Column(String, nullable=True)
|
||
|
|
modal = Column(Boolean, nullable=True)
|
||
|
|
source_id = Column(Integer, ForeignKey("sources.id", ondelete="SET NULL"), nullable=True)
|
||
|
|
|
||
|
|
source = db.relationship("Source", back_populates="tunes")
|
||
|
|
instruments = db.relationship("TuneByInstrument", back_populates="tune", cascade="all, delete-orphan")
|
||
|
|
notes = db.relationship("TuneNote", back_populates="tune", cascade="all, delete-orphan")
|
||
|
|
references = db.relationship("Reference", back_populates="tune", cascade="all, delete-orphan")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {
|
||
|
|
"id": self.id,
|
||
|
|
"name": self.name,
|
||
|
|
"key": self.key,
|
||
|
|
"modal": self.modal,
|
||
|
|
"source_id": self.source_id,
|
||
|
|
"source": self.source.to_dict() if self.source else None,
|
||
|
|
"instruments": [i.to_dict() for i in self.instruments],
|
||
|
|
"notes": [n.to_dict() for n in self.notes],
|
||
|
|
"references": [r.to_dict() for r in self.references],
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class TuneByInstrument(db.Model):
|
||
|
|
__tablename__ = "tune_by_instrument"
|
||
|
|
__table_args__ = (UniqueConstraint("tune_id", "instrument_id", name="uq_tune_instrument"),)
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
tune_id = Column(Integer, ForeignKey("tunes.id", ondelete="CASCADE"), nullable=False)
|
||
|
|
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)
|
||
|
|
date_learned = Column(Date, nullable=True)
|
||
|
|
callable = Column(Boolean, nullable=True)
|
||
|
|
review = Column(Boolean, nullable=True)
|
||
|
|
to_learn = Column(Boolean, nullable=True, default=False)
|
||
|
|
difficulty = Column(String, nullable=True)
|
||
|
|
|
||
|
|
tune = db.relationship("Tune", back_populates="instruments")
|
||
|
|
instrument = db.relationship("Instrument", back_populates="entries")
|
||
|
|
tuning = db.relationship("Tuning", back_populates="entries")
|
||
|
|
learned_from_musician = db.relationship("Musician", back_populates="instrument_entries")
|
||
|
|
notes = db.relationship("TuneByInstrumentNote", back_populates="entry", cascade="all, delete-orphan")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {
|
||
|
|
"id": self.id,
|
||
|
|
"tune_id": self.tune_id,
|
||
|
|
"instrument_id": self.instrument_id,
|
||
|
|
"instrument_name": self.instrument.name if self.instrument else None,
|
||
|
|
"learned_from_id": self.learned_from_id,
|
||
|
|
"learned_from": self.learned_from_musician.name if self.learned_from_musician else None,
|
||
|
|
"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,
|
||
|
|
"callable": self.callable,
|
||
|
|
"review": self.review,
|
||
|
|
"to_learn": self.to_learn,
|
||
|
|
"difficulty": self.difficulty,
|
||
|
|
"notes": [n.to_dict() for n in self.notes],
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class TuneNote(db.Model):
|
||
|
|
__tablename__ = "tune_notes"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
tune_id = Column(Integer, ForeignKey("tunes.id", ondelete="CASCADE"), nullable=False)
|
||
|
|
note = Column(String, nullable=True)
|
||
|
|
|
||
|
|
tune = db.relationship("Tune", back_populates="notes")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {"id": self.id, "tune_id": self.tune_id, "note": self.note}
|
||
|
|
|
||
|
|
|
||
|
|
class TuneByInstrumentNote(db.Model):
|
||
|
|
__tablename__ = "tune_by_instrument_notes"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
tune_by_instrument_id = Column(Integer, ForeignKey("tune_by_instrument.id", ondelete="CASCADE"), nullable=False)
|
||
|
|
note = Column(String, nullable=True)
|
||
|
|
|
||
|
|
entry = db.relationship("TuneByInstrument", back_populates="notes")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {"id": self.id, "tune_by_instrument_id": self.tune_by_instrument_id, "note": self.note}
|
||
|
|
|
||
|
|
|
||
|
|
class Reference(db.Model):
|
||
|
|
__tablename__ = "references"
|
||
|
|
|
||
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
|
|
tune_id = Column(Integer, ForeignKey("tunes.id", ondelete="CASCADE"), nullable=True)
|
||
|
|
link = Column(String, nullable=True)
|
||
|
|
site = Column(String, nullable=True)
|
||
|
|
|
||
|
|
tune = db.relationship("Tune", back_populates="references")
|
||
|
|
musicians = db.relationship("Musician", secondary=reference_musicians, back_populates="references")
|
||
|
|
|
||
|
|
def to_dict(self):
|
||
|
|
return {
|
||
|
|
"id": self.id,
|
||
|
|
"tune_id": self.tune_id,
|
||
|
|
"link": self.link,
|
||
|
|
"site": self.site,
|
||
|
|
"musicians": [m.to_dict() for m in self.musicians],
|
||
|
|
}
|