[Python] How do I go between two different data models using python dataclass?

Discussão em 'Python' iniciado por Stack, Maio 3, 2025.

  1. Stack

    Stack Membro Participativo

    I have a data model in my database that is different from the source data (https://statsapi.mlb.com/api/v1/schedule?sportId=1) and I'm wondering if there is a better way than pulling the data from the website, converting the dataclass to another dataclass for the sake of the database and then when I'm comparing to see if I need to update the database, having to convert from one data model to another again.

    I'm also manually removing keys that I don't need from the data model (for example, the venues dataclass will have venue:{ id: '1', venue_name: 'local baseball stadium' } and the games data will have the same venue:{ id: '1', venue_name: 'local baseball stadium' } , but I don't need to store the venue_name under the games table since I just need the venue_id, so I'm manually removing the venue_name before I load to db.

    I feel like all of this is breaking the entire spirit of modeling using dataclasses

    CREATE TABLE games (
    id int PRIMARY KEY,
    game_date timestamptz,
    game_status text,
    away_team_id int not null REFERENCES teams(id),
    home_team_id int not null REFERENCES teams(id)
    )

    CREATE TABLE game_data (
    game_id int not null REFERENCES games(id),
    away_score int,
    home_score int,
    pitchers int[],
    bullpen int[],
    weather_condition text,
    temp int,
    wind text,
    attendance int,
    first_pitch timestamptz,
    game_duration int,
    is_double_header boolean
    )


    def filter_to_dataclass(cls: dataclass, data: dict, omit_keys: Union[list, tuple]=[]) -> dataclass:
    target_keys = set(f.name for f in fields(cls))
    for omit_key in omit_keys:
    target_keys.remove(omit_key)

    return cls(
    **{k:v for k,v in data.items() if k in target_keys}
    )

    @dataclass
    class Game:
    game_pk: int
    game_data: Union[GameData, dict] = field(default_factory=dict)
    live_data: Union[LiveData, dict] = field(default_factory=dict)

    def __post_init__(self):
    self.game_data = filter_to_dataclass(GameData, self.game_data) if self.game_data else self.game_data
    self.live_data = filter_to_dataclass(LiveData, self.live_data) if self.live_data else self.live_data


    @dataclass
    class GameData:
    status: Union[GameStatus, dict]
    probable_pitchers: Union[GameProbablePitchers, dict]
    weather: Union[GameWeather, dict] = field(default_factory=dict)
    game_info: Union[GameInfo, dict] = field(default_factory=dict)

    @dataclass
    class LiveData:
    boxscore: Union[Boxscore, dict]

    @dataclass
    class Boxscore:
    teams: Union[BoxscoreTeamsHomeAndAway, dict]

    @dataclass
    class BoxscoreTeamsHomeAndAway:
    away: Union[BoxscoreTeam, dict]
    home: Union[BoxscoreTeam, dict]

    @dataclass
    class BoxscoreTeam:
    team: Union[Team, dict]
    pitchers: list[int]
    bullpen: list[int]
    batting_order: list[int]

    Continue reading...

Compartilhe esta Página