Sqlalchemy-Marshmallow — вложенное поле не отображает никаких данных

У меня не было проблем с использованием вложенных полей в моем приложении для фляг при использовании marshmallow-sqlalchemy с Flask-SQLAlchemy. Теперь, когда я перешел с Flask-SQLAlchemy только на SQLAlchemy (по нескольким несущественным причинам), мои вложенные поля больше не отображают никаких данных. Я чувствую, что это может иметь какое-то отношение к сеансу SQLAlchemy, который не передается во вложенные поля.

Мой проект выглядит следующим образом:

engine = create_engine(config.SQLALCHEMY_DATABASE_URI, echo=True)
Session = orm.scoped_session(orm.sessionmaker())
Session.configure(bind=engine)    
Base = declarative_base(bind=engine)

class PodcastModel(Base):
    __tablename__ = 'podcasts'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    host = db.Column(db.String(80))
    episodes = relationship(EpisodeModel, backref='episode', lazy='dynamic')

    @classmethod
    def dump(cls, podcast):
        podcast_schema = PodcastSchemaNested()
        podcast_output = podcast_schema.dump(podcast).data
        return podcast_output

class EpisodeModel(Base):
    __tablename__ = 'episodes'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(200))
    length = db.Column(db.Float(precision=2))    
    podcast_id = db.Column(db.Integer, db.ForeignKey('podcasts.id', ondelete='CASCADE'))

class BaseSchema(ModelSchema):
    class Meta:
        sqla_session = Session
        ordered = True 

class PodcastSchemaNested(BaseSchema):
    id = fields.Integer()
    name = fields.Str()
    host = fields.Str()
    episodes = fields.Nested('EpisodeSchema', many=True)

class EpisodeSchema(BaseSchema):
    id = fields.Integer()
    name = fields.Str() 
    length = fields.Float()

И вывод json следующий:

{
"id": 1,
"name": "Podcast Name",
"host": "Podcast Host",
"episodes": [

]
}

Я боролся с этой проблемой уже несколько часов, и любой вклад в то, почему вложенные поля не отображают никаких данных, был бы очень признателен. Благодарю вас!


person Sean    schedule 02.04.2019    source источник


Ответы (2)


У меня нет недавнего опыта работы с SQLAlchemy, но, возможно, проверьте все ваши методы сериализации/дампа, чтобы убедиться, что все знает, как писать себя. Мне непонятно, что Эпизоды могут.

В противном случае я бы начал с этого:

  • Ваша база данных существует?
  • Ваша конфигурация все еще указывает на это правильно?
  • Вы выполнили всю настройку базы данных?
  • Все ли было добавлено и закреплено за вашей сессией?
  • Не заполняется только список эпизодов?
  • Должны ли вы получать только один список подкастов?
  • Есть ли опечатка в файле, содержащем данные эпизода или данные подкаста?
  • Должны ли некоторые требования (установки pip) меняться без фляги (следите за заглавными буквами)?

  • Вы получили последнюю версию sqlalchemy? Вы проверили журнал изменений (он делает некоторые соединения по-разному и т. д.)

Мои очень старые примеры

Base = declarative_base()
Base.metadata.bind=engine

Актуальны ли метаданные?

(Я пришел сюда через ваш пост на upwork, и мне было любопытно - не уверен, что это вообще поможет отклеить вас). Удачи.

person AnnW    schedule 03.04.2019
comment
Анна, спасибо за подробный ответ. Я буду использовать все эти пункты для диагностики в следующий раз, когда столкнусь с проблемой! Я определил, что проблема связана с тем, как я обрабатывал сеансы на каждой отдельной модели. Поскольку я не использовал сеанс с заданной областью для каждой модели, я предполагаю, что сеанс никогда не передавался каждому вложенному полю, поэтому был пустой массив данных. - person Sean; 05.04.2019

В итоге я заставил работать вложенные поля, изменив свой файл базы данных с приведенного выше на -

from common import config
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref


engine = db.create_engine(config.SQLALCHEMY_DATABASE_URI, echo=True)
session = scoped_session(sessionmaker(bind=engine))
Base = declarative_base()

И в моих методах модели, где я обращаюсь к базе данных и запрашиваю ее, вместо -

@classmethod
def find_by_name(cls, name):
    session = Session()
    episode = session.query(cls).filter_by(name=name).first()  
    session.close()
    return episode       

Вместо этого я не создаю новый сеанс, а затем закрываю его, а использую импортируемый сеанс с заданной областью.

from common.db.base import Base, session

@classmethod
def find_by_name(cls, name):
    episode = session.query(cls).filter_by(name=name).first()  
    return episode    

Тем не менее, я все еще не уверен, что это вызовет некоторые проблемы из-за того, что это неправильный способ обработки сеансов... Нужно продолжить чтение документации.

person Sean    schedule 05.04.2019