0

所以我很难用标题中的技术解决我的问题。

我有几个玩家加入了一个游戏。所以一个游戏有很多玩家。我正在使用 python flask、带有 sqlite 后端的 sqlalchemy 和 marshmallow 进行编组。

这些是相关文件:

database.py - 初始化数据库

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True)
db_session = scoped_session(sessionmaker(bind=engine))

Base = declarative_base()
Base.query = db_session.query_property()


def init_db():
    from dom.database.model_game import Game
    from dom.database.model_player import Player

    Base.metadata.create_all(bind=engine)

这是我的播放器模型和架构:

from sqlalchemy import Column, String, Integer, Boolean, ForeignKey
from sqlalchemy.orm import relationship
from flask_marshmallow import Schema
from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
from marshmallow_sqlalchemy.fields import Nested

from dom.database.database import Base, db_session



class Player(Base):
    __tablename__ = "player"
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    nickname = Column(String, nullable=True)
    in_game = Column(Boolean, nullable=True)

    # belongs to one
    game_id = Column(Integer, ForeignKey(
        'game.id', ondelete="SET NULL"), nullable=True)
    game = relationship("Game", back_populates="players")

# THIS WILL WORK FINE
# class PlayerSchema(Schema):
#     class Meta:
#         fields = ("id", "name", "nickname", "in_game", "game_id")

class PlayerSchema(SQLAlchemySchema):
    class Meta:
        sqla_session = db_session
        model = Player
        load_instance = True

    id = auto_field()
    name = auto_field
    nickname = auto_field()
    in_game = auto_field()
    game_id = auto_field()

player_schema = PlayerSchema()
players_schema = PlayerSchema(many=True)

这是我的游戏模型和架构:

from sqlalchemy import Column, String, Integer
from sqlalchemy.orm import relationship
from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
from marshmallow_sqlalchemy.fields import Nested

from dom.database.database import Base, db_session
from dom.database.model_player import Player, PlayerSchema



class Game(Base):
    __tablename__ = "game"
    id = Column(Integer, primary_key=True)
    game = Column(String, nullable=False)
    variant = Column(String, nullable=False)
    active_player = Column(Integer, nullable=False)
    throw_round = Column(Integer, nullable=False)
    game_state = Column(String, nullable=False)

    # has many
    players = relationship(Player, back_populates="game")


class GameSchema(SQLAlchemySchema):
    class Meta:
        sqla_session = db_session
        model = Game
        load_instance = True

    id = auto_field()
    game = auto_field()
    variant = auto_field()
    active_player = auto_field()
    throw_round = auto_field()
    game_state = auto_field()

    players = Nested(PlayerSchema, many=True)

game_schema = GameSchema()
games_schema = GameSchema(many=True)

因此,如果在我的播放器模型中使用代码中的行标记为“这将正常工作”的模式,我可以解决关系。但是随着我将继续实现与玩家相关的其他关系,例如个人资料图片,我将根据我在游戏模式中所做的更改玩家模式,从而导致此堆栈跟踪:

Traceback (most recent call last):
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/ext/declarative/clsregistry.py", line 311, in _resolve_name
    rval = d[token]
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/util/_collections.py", line 739, in __missing__
    self[key] = val = self.creator(key)
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/ext/declarative/clsregistry.py", line 290, in _access_cls
    return self.fallback[key]
KeyError: 'Game'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/patrick/projects/theallnewdom/server/run.py", line 2, in <module>
    from dom import app, socketio
  File "/home/patrick/projects/theallnewdom/server/dom/__init__.py", line 9, in <module>
    from dom.api.routes import initialize_routes
  File "/home/patrick/projects/theallnewdom/server/dom/api/routes.py", line 1, in <module>
    from dom.api.game import GamesApi, GameApi
  File "/home/patrick/projects/theallnewdom/server/dom/api/game.py", line 4, in <module>
    from dom.database.model_game import Game, games_schema, game_schema
  File "/home/patrick/projects/theallnewdom/server/dom/database/model_game.py", line 8, in <module>
    from dom.database.model_player import Player, PlayerSchema
  File "/home/patrick/projects/theallnewdom/server/dom/database/model_player.py", line 46, in <module>
    class PlayerSchema(SQLAlchemySchema):
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/marshmallow/schema.py", line 120, in __new__
    klass._declared_fields = mcs.get_declared_fields(
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/marshmallow_sqlalchemy/schema/sqlalchemy_schema.py", line 94, in get_declared_fields
    fields.update(mcs.get_auto_fields(fields, converter, opts, dict_cls))
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/marshmallow_sqlalchemy/schema/sqlalchemy_schema.py", line 104, in get_auto_fields
    {
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/marshmallow_sqlalchemy/schema/sqlalchemy_schema.py", line 105, in <dictcomp>
    field_name: field.create_field(
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/marshmallow_sqlalchemy/schema/sqlalchemy_schema.py", line 28, in create_field
    return converter.field_for(model, column_name, **self.field_kwargs)
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/marshmallow_sqlalchemy/convert.py", line 170, in field_for
    prop = model.__mapper__.get_property(property_name)
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/mapper.py", line 2043, in get_property
    configure_mappers()
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/mapper.py", line 3255, in configure_mappers
    mapper._post_configure_properties()
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/mapper.py", line 1950, in _post_configure_properties
    prop.init()
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/interfaces.py", line 196, in init
    self.do_init()
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/relationships.py", line 1983, in do_init
    self._process_dependent_arguments()
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/relationships.py", line 2045, in _process_dependent_arguments
    self.target = self.entity.persist_selectable
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 883, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/orm/relationships.py", line 1950, in entity
    argument = self.argument()
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/ext/declarative/clsregistry.py", line 315, in _resolve_name
    self._raise_for_name(name, err)
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/ext/declarative/clsregistry.py", line 293, in _raise_for_name
    util.raise_(
  File "/home/patrick/projects/theallnewdom/server/.venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 178, in raise_
    raise exception
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Player->player, expression 'Game' failed to locate a name ('Game'). If this is a class name, consider adding this relationship() to the <class 'dom.database.model_player.Player'> class after both dependent classes have been defined.

有人可以向我指出如何改变以使其正常工作的大致方向吗?

在此先感谢,最好的问候,帕特里克

4

0 回答 0