Вы правильно поняли, что хотите строить свои объекты непосредственно из данных словаря, но просто на неправильном пути, когда дело доходит до разницы между class
, instance
и тем, как SQLAlchemy ORM работает с ними,Но не волнуйтесь, это то, чему мы все должны были научиться в тот или иной момент.
Думайте о class
как о рецепте, а instance
как о пироге.Мы используем рецепт, чтобы сделать торт, и мы можем создать столько тортов, сколько нам нужно, используя рецепт.
Итак, имея в виду, этот фрагмент кода здесь:
for key, value in d.items():
setattr(Series, key, value)
... не делает торт, он меняет рецепт или отбрасывает метафору, вы модифицируете class
.На самом деле эта часть кода работает - setattr()
будет работать на class
объектах так же, как и на instance
объектах, проблема возникает позже, когда вы пытаетесь добавить объект class
в SQLAlchemy.сессия.Это сообщение об ошибке, которое возникает в session.add(Series)
:
sqlalchemy.orm.exc.UnmappedInstanceError: Класс 'sqlalchemy.ext.declarative.api.DeclarativeMeta' не сопоставлен;был ли предоставлен класс (__main__.Series
), где требовался экземпляр?
Когда вы создаете класс SQLAlchemy ORM, вы наследуете от declarative_base
экземпляра (обычно называемого Base
) и выглядит какэто: class Series(Base):
.Это позволяет SQLAlchemy делать некоторые вещи за кулисами при создании instance
, который используется для преобразования изменений в instance
в изменения в базе данных.Когда вы добавляете объект в сеанс, SQLAlchemy ищет это «инструментарий», но он не существует на class
, только на instances
, сделанном с этим class
, поэтому возникает ошибка.
Возвращаясь к сообщению об ошибке, SQLAlchemy на самом деле обработал ошибку, которую вы сделали: was a class (__main__.Series) supplied where an instance was required?
.
Самая простая часть - это исправление ошибки.Мы создаем instance
нашего class
, используя данные словаря, добавляем instance
к сеансу и фиксируем:
instance = Series(**d)
# The ** is called dictionary unpacking which you can google if you need.
# If an attribute value doesn't exist in the dictionary, it will be None by
# default.
session.add(instance)
session.commit()