英文:
Using Python, Flask, SQLAlchemy, Marshmallow -- dumps method returns an empty list of objects with my many=true schema
问题
以下是两个SQL表的类定义:
# 数据库中的Players表
class Players(masdb.Model):
__tablename__ = 'players'
id = masdb.Column(masdb.Integer, primary_key=True)
game_key = masdb.Column(masdb.String(255))
games = masdb.relationship('Game', backref='player', lazy=True)
def __init__(self, game_key): # 构造函数
self.game_key = game_key
# 数据库中的Game表
class Game(masdb.Model):
__tablename__ = 'game'
id = masdb.Column(masdb.Integer, primary_key=True)
settlement_name = masdb.Column(masdb.String(50))
created_at = masdb.Column(masdb.DateTime, default=datetime.datetime.now)
player_id = masdb.Column(masdb.Integer, ForeignKey('players.id'))
def __init__(self, settlement_name, player_id):
self.settlement_name = settlement_name
self.player_id = player_id
以下是用于序列化数据的模式:
class PlayersSchema(ma.Schema):
class Meta:
fields = ('id', 'game_key')
class GameSchema(ma.Schema):
class Meta:
fields = ('id', 'settlement_name', 'created_at', 'player_id')
# 用于序列化数据的类
player_schema = PlayersSchema()
players_schema = PlayersSchema(many=True)
game_schema = GameSchema()
games_schema = GameSchema(many=True)
最后,以下是我尝试返回包含多个游戏条目的JSON的部分:
@app.route('/getGamesByGameKey/<cookieGame_Key>/', methods=['GET'])
def getGamesByGameKey(cookieGame_Key):
findPlayerStatement = select(Players).filter_by(game_key=cookieGame_Key) # SQL语句
playerObject = masdb.session.execute(findPlayerStatement).first() # 执行语句。我认为first()只会在找到第一个结果时停止搜索,总是返回一个包含1个元素的数组。
findGamesStatement = select(Game).filter_by(player_id=playerObject[0].id) # 由于上述原因,数据只会有一个条目,因此使用playerObject[0]
games = masdb.session.execute(findGamesStatement).all()
results = games_schema.dump(games)
return jsonify(results)
但是当我到达results = games_schema.dump(games)
时,它返回了一个包含空对象的数组:
[
{},
{},
{}
]
我得出的结论是:
games = masdb.session.execute(findGamesStatement).all()
这行产生了一个包含3个对象的数组,这正如我所期望的。所有数据都存储在变量中。
如果我将 .all()
更改为 .first()
,它将只返回一个对象,甚至使用具有 many=True
的 games_schema
也可以工作!只是...只返回单个项目。因此,模式本身似乎没有任何问题。输出如下:
[
{
"created_at": "2023-04-10T20:23:39",
"id": 120,
"player_id": 118,
"settlement_name": "Multi Game to Get"
}
]
所以在序列化对象数组时出现了一些问题。这些症状与其他人发布的一些缺少模式中的 many=True
类似。但是我已经有了。
英文:
Here are my classes for the two SQL tables I'll be using:
#Players Table for the database
class Players(masdb.Model):
__tablename__ = 'players'
id=masdb.Column(masdb.Integer, primary_key=True)
game_key=masdb.Column(masdb.String(255))
games=masdb.relationship('Game', backref='player', lazy=True)
def __init__(self, game_key): # constructor function
self.game_key = game_key
#Game table for the database
class Game(masdb.Model):
__tablename__ = 'game'
id = masdb.Column(masdb.Integer, primary_key=True)
settlement_name = masdb.Column(masdb.String(50))
created_at = masdb.Column(masdb.DateTime, default=datetime.datetime.now)
player_id = masdb.Column(masdb.Integer, ForeignKey('players.id'))
def __init__(self, settlement_name, player_id):
self.settlement_name = settlement_name
self.player_id = player_id
Here are the schemas for serializing the data:
class PlayersSchema(ma.Schema):
class Meta:
fields = ('id', 'game_key')
class GameSchema(ma.Schema):
class Meta:
fields = ('id', 'settlement_name', 'created_at', 'player_id')
# Classes for serializing data
player_schema = PlayersSchema()
players_schema = PlayersSchema(many=True)
game_schema = GameSchema()
games_schema = GameSchema(many=True)
And finally, here I am trying to return a json with multiple game entries:
@app.route('/getGamesByGameKey/<cookieGame_Key>/', methods =['GET'])
def getGamesByGameKey(cookieGame_Key):
findPlayerStatement = select(Players).filter_by(game_key = cookieGame_Key) # SQL statement
playerObject = masdb.session.execute(findPlayerStatement).first() # Executes the statement. I think first() just stops the search at the first find always returning an array of 1.
findGamesStatement = select(Game).filter_by(player_id = playerObject[0].id) #Data will only ever have a single entry due to the above, hence the playerObject[0]
games = masdb.session.execute(findGamesStatement).all()
results = games_schema.dump(games)
return jsonify(results)
But when I get to results = games_schema.dump(games)
it returns an array of empty objects
I created 3 games in my database for my test and associated them all to a single player for my test. When I send the request for them I get the following response back:
[
{},
{},
{}
]
What I've deduced:
games = masdb.session.execute(findGamesStatement).all()
line is producing an array of 3 objects exactly as expected and the data is all being stored in the variable.
If I change the .all() to .first() it will return just a single object, and even using the games_schema (which has many=True) it will work! It just... only returns the single item. So there doesn't appear to be anything wrong with the schema itself. The output is as follows:
[
{
"created_at": "2023-04-10T20:23:39",
"id": 120,
"player_id": 118,
"settlement_name": "Multi Game to Get"
}
]
So there's something going wrong with serializing an array of objects. The symptoms of this are similar to others who have posted that were missing the many=True for the schema. But I have that.
答案1
得分: 0
你的查询返回一个仅包含一个元素的元组列表:(game,)。 schema(many=True) 作用在元组上,而不是游戏上,因此它找不到任何内容,返回一个空字典列表。
当使用first时,你返回第一个元组,而 schema(many=True) 将这个(仅包含一个元素的)元组视为列表,并正确地输出游戏。
你需要重新设计查询或其输出,以返回一个游戏列表,而不是一个仅包含游戏作为第一个元素的元组列表。
英文:
Your query returns a list of tuples with a single element: (game,). The schema(many=True) acts on the tuple, not the game, so it doesn't find anything and returns a list of empty dicts.
When using first, you return the first tuple and the schema(many=True) treats this (one element) tuple as a list and dumps the game correctly.
You need to rework the query or its output to return a list of games, not a list of tuples with game as first and only element.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论