Запрашивать, объединять и фильтровать между 3 таблицами в Flask-SQLAlchemy? - PullRequest
0 голосов
/ 17 октября 2019

У меня есть 3 модели Flask-SQLAlchemy (и одна таблица ассоциации) со следующими отношениями:
Matchup <-> Команда (многие ко многим)
Команда -> TeamPoint (один ко многим))

В идеале я хотел бы создать оператор запроса / соединения, который будет запрашивать Matchup (который содержит 2 команды) и возвращать записи TeamPoint для каждой команды, которые имеют одинаковые week в качестве матча. Я проверил несколько запросов чистого SQL, и я могу почти получить правильный результат с этими JOIN:

SELECT * FROM matchup m JOIN team_matchup_map tmm ON m.id=tmm.matchup_id # Joining the Matchup side JOIN team t ON tmm.team_id=t.id # Joining the Team side of the association table JOIN team_point tp ON tp.team_key=t.team_key # Joining the TeamPoint table AND m.week=2 AND tp.week=2 AND t.team_id=9 # Filtering on week and team_id

Это дает мне команду с team_id = 9, но не дает мне другую команду в матче. Есть ли хороший способ сделать похожий запрос / фильтр для нескольких таблиц в Flask-SQLAlchemy? В настоящее время я делаю это в 2 запроса, но, похоже, это не самое эффективное решение. Ниже приведены мои Модели и мой маршрут с запросами:

class Team(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    team_id = db.Column(db.Integer, nullable=False)
    team_key = db.Column(db.String(30), nullable=False)
    name = db.Column(db.String(20), unique=True, nullable=False)
    league_id = db.Column(db.Integer, db.ForeignKey('league.league_id'), nullable=False)
    team_stats = db.relationship('TeamStat', backref='team', lazy=True)
    team_points = db.relationship('TeamPoint', backref='team', lazy=True)


class TeamPoint(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    week = db.Column(db.Integer, nullable=True)
    total = db.Column(db.Integer, nullable=True)
    team_key = db.Column(db.String(30), db.ForeignKey('team.team_key'))


class Matchup(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    week = db.Column(db.Integer, nullable=False)
    teams = db.relationship('Team', secondary=team_matchup_map, backref='matchup')
    stat_winners = db.relationship('StatWinner', lazy=True)

team_matchup_map = db.Table('team_matchup_map',
                           db.Column('team_id', db.ForeignKey('team.id'), primary_key=True),
                           db.Column('matchup_id', db.ForeignKey('matchup.id'), primary_key=True),
                           )

Вот мой текущий код маршрута с 2 запросами:

@team.route('/matchups/<league_id>/<team_id>', methods=['GET'])
def matchups(league_id=get_user_league().league_id, team_id=get_user_team().team_id):
    week = request.args.get('week')
    # First, querying the Matchup table for the matchup involving the primary team on the given week
    # This provides both teams in the given matchup.
    matchup = Matchup.query.filter(Matchup.teams.any(league_id=league_id, team_id=team_id), Matchup.week == week).first()

    # Next, looping through each team to query the TeamPoint table for the team entry on the same week
    team_points = {}
    for mu_team in matchup.teams:
        if mu_team.team_id == team_id:
            primary_team = mu_team
            team_points[primary_team.team_key] = TeamPoint.query.filter_by(week=week, team_key=mu_team.team_key).first()            
        else:
            opponent = mu_team
            team_points[opponent.team_key] = TeamPoint.query.filter_by(week=week, team_key=mu_team.team_key).first()            

    return render_template('matchups.html', matchup=matchup, primary_team=primary_team, opponent=opponent, team_points=team_points)
...