Using Python, Flask, SQLAlchemy, Marshmallow — dumps method returns an empty list of objects with my many=true schema

huangapple go评论63阅读模式
英文:

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=Truegames_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__ = &#39;players&#39;

    id=masdb.Column(masdb.Integer, primary_key=True)
    game_key=masdb.Column(masdb.String(255))
    games=masdb.relationship(&#39;Game&#39;, backref=&#39;player&#39;, lazy=True)

    def __init__(self, game_key): # constructor function
        self.game_key = game_key

#Game table for the database
class Game(masdb.Model):
    __tablename__ = &#39;game&#39;

    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(&#39;players.id&#39;)) 

    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 = (&#39;id&#39;, &#39;game_key&#39;)


class GameSchema(ma.Schema): 
    class Meta:
        fields = (&#39;id&#39;, &#39;settlement_name&#39;, &#39;created_at&#39;, &#39;player_id&#39;)

# 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(&#39;/getGamesByGameKey/&lt;cookieGame_Key&gt;/&#39;, methods =[&#39;GET&#39;])
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:

[
    {
        &quot;created_at&quot;: &quot;2023-04-10T20:23:39&quot;,
        &quot;id&quot;: 120,
        &quot;player_id&quot;: 118,
        &quot;settlement_name&quot;: &quot;Multi Game to Get&quot;
    }
]

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.

huangapple
  • 本文由 发表于 2023年4月11日 12:29:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75982424.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定