Merge pull request 'fix: refactor Roster from 26 FK columns to RosterSlot junction table (#29)' (#58) from ai/paper-dynasty-database#29 into next-release
Reviewed-on: #58
This commit is contained in:
commit
7295e77c96
@ -498,51 +498,34 @@ class Roster(BaseModel):
|
||||
team = ForeignKeyField(Team)
|
||||
name = CharField()
|
||||
roster_num = IntegerField()
|
||||
card_1 = ForeignKeyField(Card)
|
||||
card_2 = ForeignKeyField(Card)
|
||||
card_3 = ForeignKeyField(Card)
|
||||
card_4 = ForeignKeyField(Card)
|
||||
card_5 = ForeignKeyField(Card)
|
||||
card_6 = ForeignKeyField(Card)
|
||||
card_7 = ForeignKeyField(Card)
|
||||
card_8 = ForeignKeyField(Card)
|
||||
card_9 = ForeignKeyField(Card)
|
||||
card_10 = ForeignKeyField(Card)
|
||||
card_11 = ForeignKeyField(Card)
|
||||
card_12 = ForeignKeyField(Card)
|
||||
card_13 = ForeignKeyField(Card)
|
||||
card_14 = ForeignKeyField(Card)
|
||||
card_15 = ForeignKeyField(Card)
|
||||
card_16 = ForeignKeyField(Card)
|
||||
card_17 = ForeignKeyField(Card)
|
||||
card_18 = ForeignKeyField(Card)
|
||||
card_19 = ForeignKeyField(Card)
|
||||
card_20 = ForeignKeyField(Card)
|
||||
card_21 = ForeignKeyField(Card)
|
||||
card_22 = ForeignKeyField(Card)
|
||||
card_23 = ForeignKeyField(Card)
|
||||
card_24 = ForeignKeyField(Card)
|
||||
card_25 = ForeignKeyField(Card)
|
||||
card_26 = ForeignKeyField(Card)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.team} Roster"
|
||||
|
||||
# def get_cards(self, team):
|
||||
# all_cards = Card.select().where(Card.roster == self)
|
||||
# this_roster = []
|
||||
# return [this_roster.card1, this_roster.card2, this_roster.card3, this_roster.card4, this_roster.card5,
|
||||
# this_roster.card6, this_roster.card7, this_roster.card8, this_roster.card9, this_roster.card10,
|
||||
# this_roster.card11, this_roster.card12, this_roster.card13, this_roster.card14, this_roster.card15,
|
||||
# this_roster.card16, this_roster.card17, this_roster.card18, this_roster.card19, this_roster.card20,
|
||||
# this_roster.card21, this_roster.card22, this_roster.card23, this_roster.card24, this_roster.card25,
|
||||
# this_roster.card26]
|
||||
def get_cards(self):
|
||||
return (
|
||||
Card.select()
|
||||
.join(RosterSlot)
|
||||
.where(RosterSlot.roster == self)
|
||||
.order_by(RosterSlot.slot)
|
||||
)
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
table_name = "roster"
|
||||
|
||||
|
||||
class RosterSlot(BaseModel):
|
||||
roster = ForeignKeyField(Roster, backref="slots")
|
||||
slot = IntegerField()
|
||||
card = ForeignKeyField(Card, backref="roster_slots")
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
table_name = "rosterslot"
|
||||
indexes = ((("roster", "slot"), True),)
|
||||
|
||||
|
||||
class Result(BaseModel):
|
||||
away_team = ForeignKeyField(Team)
|
||||
home_team = ForeignKeyField(Team)
|
||||
@ -744,6 +727,7 @@ if not SKIP_TABLE_CREATION:
|
||||
db.create_tables(
|
||||
[
|
||||
Roster,
|
||||
RosterSlot,
|
||||
BattingStat,
|
||||
PitchingStat,
|
||||
Result,
|
||||
|
||||
65
migrations/migrate_roster_junction_table.py
Normal file
65
migrations/migrate_roster_junction_table.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""
|
||||
Migration: Replace 26 FK columns on Roster with RosterSlot junction table.
|
||||
|
||||
Creates the `rosterslot` table and migrates existing lineup data from the
|
||||
card_1..card_26 columns. Safe to re-run (skips rosters already migrated).
|
||||
|
||||
Usage:
|
||||
python migrations/migrate_roster_junction_table.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
from app.db_engine import db, Roster, RosterSlot
|
||||
|
||||
SLOTS = 26
|
||||
|
||||
|
||||
def migrate():
|
||||
db.connect(reuse_if_open=True)
|
||||
|
||||
# Create the table if it doesn't exist yet
|
||||
db.create_tables([RosterSlot], safe=True)
|
||||
|
||||
# Read raw rows from the old schema via plain SQL so we don't depend on
|
||||
# the ORM model knowing about the legacy card_N columns.
|
||||
cursor = db.execute_sql("SELECT * FROM roster")
|
||||
columns = [desc[0] for desc in cursor.description]
|
||||
|
||||
migrated = 0
|
||||
skipped = 0
|
||||
|
||||
with db.atomic():
|
||||
for row in cursor.fetchall():
|
||||
row_dict = dict(zip(columns, row))
|
||||
roster_id = row_dict["id"]
|
||||
|
||||
already_migrated = (
|
||||
RosterSlot.select().where(RosterSlot.roster == roster_id).exists()
|
||||
)
|
||||
if already_migrated:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
slots_to_insert = []
|
||||
for slot_num in range(1, SLOTS + 1):
|
||||
col = f"card_{slot_num}_id"
|
||||
card_id = row_dict.get(col)
|
||||
if card_id is not None:
|
||||
slots_to_insert.append(
|
||||
{"roster": roster_id, "slot": slot_num, "card": card_id}
|
||||
)
|
||||
|
||||
if slots_to_insert:
|
||||
RosterSlot.insert_many(slots_to_insert).execute()
|
||||
migrated += 1
|
||||
|
||||
print(f"Migration complete: {migrated} rosters migrated, {skipped} already done.")
|
||||
db.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
migrate()
|
||||
Loading…
Reference in New Issue
Block a user