В настоящее время пытаюсь внедрить систему рекомендаций для игр, но у меня возникают некоторые проблемы с REST-API с flask / sqlalchemy
Я успешно реализовал маршруты для получения игр и пытаюсь применить больше фильтров. Я хочу фильтровать извлеченные игры по жанрам - что работает, когда я фильтрую по идентификатору одного жанра - проблема возникает, когда я пытаюсь фильтровать по нескольким жанрам.
Маршрут должен выглядеть как / игры? Жанры = 3,7,8
В базе данных есть таблица игр и жанров, и между ними существует связь один ко многим, поэтому одна игра связана с несколькими жанрами.
Это Game db.Model
game_genres = db.Table('game_genres',
db.Column('game_id', db.Integer, db.ForeignKey(
'games.id'), primary_key=True),
db.Column('genre_id', db.Integer, db.ForeignKey(
'genres.id'), primary_key=True),
db.PrimaryKeyConstraint('game_id', 'genre_id')
)
game_platforms = db.Table('game_platforms',
db.Column('game_id', db.Integer, db.ForeignKey(
'games.id'), primary_key=True),
db.Column('platform_id', db.Integer, db.ForeignKey(
'platforms.id'), primary_key=True),
db.PrimaryKeyConstraint('game_id', 'platform_id')
)
class Game(db.Model):
__tablename__ = 'games'
id = db.Column(db.Integer, unique=True, primary_key=True)
title = db.Column(db.String, nullable=False)
description = db.Column(db.String)
year = db.Column(db.Integer)
genres = db.relationship(
'Genre',
secondary=game_genres,
lazy='subquery',
backref=db.backref('genres', lazy=True, cascade='all, delete')
)
platforms = db.relationship(
'Platform',
secondary=game_platforms,
lazy='subquery',
backref=db.backref('games', lazy=True, cascade='all, delete')
)
def __init__(self, title: str):
self.title = title
def __repr__(self):
return f'<Game {self.title}>'
@property
def to_json(self):
genres = []
for genre in self.genres:
genres.append(genre.to_json)
platforms = []
for platform in self.platforms:
platforms.append(platform.to_json)
return {
'id': self.id,
'title': self.title,
'description': self.description,
'year': self.year,
'genres': genres,
'platforms': platforms,
}
@classmethod
def return_all(self, offset, limit):
return {'games': [g.to_json for g in self.query.order_by(Game.id).offset(offset).limit(limit).all()]}
@classmethod
def return_bygenres(self, offset, limit, genres2):
return {'games': [g.to_json for g in self.query\
.join(Game.genres, aliased=True)\
.filter(or_(*[id.like(gid)for gid in genres2])).all().order_by(Game.id).offset(offset).limit(limit).all()]}
Это соответствующая модель жанра
class Genre(db.Model):
__tablename__ = "genres"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
def __init__(self, name):
self.name = name
def __repr__(self):
return f'<Genre {self.name}>'
@property
def to_json(self):
return {
'id': self.id,
'name': self.name,
}
Маршруты выглядят так
GAME_PARSER = reqparse.RequestParser()
GAME_PARSER.add_argument('offset', type=int)
GAME_PARSER.add_argument('limit', type=int)
GAME_PARSER.add_argument('genres')
class AllGames(Resource):
def get(self):
args = GAME_PARSER.parse_args()
offset = 0 if args.offset is None else args.offset
limit = 100 if args.limit is None else args.limit
genres = args.genres
return Game.return_bygenres(offset, limit, genres.split(","))
Я нашел текущий запрос на другой пост, но он выдает ошибку. Я получаю сообщение об ошибке: «У объекта buildtin_function_or_method нет атрибута» вроде «»
Я пробовал другие способы, например использование any, has или in function, но все они возвращают вышеуказанную ошибку .
Использование self.query.join(Game.genres, aliased=True).filter_by(id==1).order_by(Game.id).offset(offset).limit(limit).all()
работает только при возврате игр с идентификатором жанра 1
Я не уверен, что в запросе я ошибся или модель не реализована должным образом для такой запрос.
Это мой первый раз кодирование с flask и sqlalchemy, поэтому я был бы признателен за любую форму ввода!