Flask SQLAlchemy Marshmallow Отношение один ко многим - PullRequest
0 голосов
/ 04 мая 2020

Так что мне трудно решить мою проблему с указанной технологией в названии.

У меня есть несколько игроков, присоединяющихся к игре. Так что в одной игре много игроков. Я использую python flask, sqlalchemy с бэкэндом sqlite и зефир для маршаллинга.

Это соответствующие файлы:

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.

Может кто-нибудь пожалуйста указать мне общее направление, что изменить, чтобы заставить его работать?

Заранее спасибо, с наилучшими пожеланиями, Патрик

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...