SQLAlchemy Recursion - PullRequest
       12

SQLAlchemy Recursion

1 голос
/ 09 ноября 2011

Я прекрасно провожу время, изучая Python, но я только немного застрял при попытке включить рекурсивную функцию в SQLAlchemy.

По сути, есть функция, которая создает экземпляр класса для помещения в базу данных. Внутри этой функции я получаю от пользователя информацию о том, имеет ли экземпляр родительский класс (определенный с помощью таблицы самоссылочной смежности). Если это так, функция вызывается снова, рекурсивно. Эта функция работает, если родительский класс не нужен, но всякий раз, когда активируется рекурсивный элемент, происходит сбой.

Мой код такой:

engine = create_engine('sqlite:///recDB.db')
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base()

class IngList(Base):
    __tablename__ = "ingList"

    id = Column(Integer, primary_key = True)
    ingredient = Column(String, nullable=False)
    parentIng = Column(Integer, ForeignKey('ingList.id'))
    children = relationship("IngList",backref=backref('parent', remote_side=[id]))

    def __init__(self, ingredient):
        self.ingredient = ingredient

def addIngredient(ingredient):
    global newIngList
    newIng = IngList(ingName) #create new class instance
    parentIng = raw_input("To add parent ingredient, type it.  Otherwise press enter")
    if parentIng != '':
        parentIngObj = addIngredient(parentIng) # Recursion!
        newIng.parentIng = parentIngObj
    newIngList.append(newIng)

if __name__ == '__main__':
    newIngList = []
    ingredient = raw_input("Enter new ingredient")
    addIngredient(ingredient)
    for ing in newIngList
        session.add(ing)
    session.commit()

Я сделал этот образец простым, чтобы он был читабельным, но если мне не хватает важной информации, пожалуйста, дайте мне знать.

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

Это как-то связано с нетерпеливой загрузкой ? Я видел это в документации, но не совсем понял.

Я получаю ошибку:

Traceback (most recent call last):
  File "C:\workspace\recipes\langProc.py", line 102, in <module>
    session.commit()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 645, in commit
    self.transaction.commit()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 313, in commit
    self._prepare_impl()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 297, in _prepare_impl
    self.session.flush()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 1547, in flush
    self._flush(objects)
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 1616, in _flush
    flush_context.execute()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\unitofwork.py", line 328, in execute
    rec.execute(self)
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\unitofwork.py", line 472, in execute
    uow
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 2153, in _save_obj
    execute(statement, params)
  File "c:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1399, in execute
    params)
  File "c:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1532, in _execute_clauseelement
    compiled_sql, distilled_params
  File "c:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1640, in _execute_context
    context)
  File "c:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1633, in _execute_context
    context)
  File "c:\Python27\lib\site-packages\sqlalchemy\engine\default.py", line 330, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.InterfaceError: (InterfaceError) Error binding parameter 0 
- probably unsupported type.
u'UPDATE "ingList" SET "parentIng"=? WHERE "ingList".id = ?' 
(<assignDB.IngList object at 0x00000000096969E8>, 4)

Ответы [ 2 ]

3 голосов
/ 11 ноября 2011

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

  • вместо newIng.parentIng = parentIngObj у вас должно быть newIng.parent = parentIngObj. Я считаю, что это должно решить проблему.
    Таким образом, вы должны назначить родительский экземпляр объекту отношения, а не его ключу. Используя J.F. Предложения Себастьяна тоже могут сработать, если объекты уже сохранены в базе данных, но новым экземплярам еще не присвоен id
  • addIngredient(...) имеет две проблемы:
    • опечатка: параметр ingredient следует переименовать в ingName или наоборот
    • большая проблема: addIngredient(...) не возвращает никакого значения, поэтому фактически вы присваиваете None стороне parent отношения.
      Опять же, учитывая, что это просто пример кода, у вас могут не быть этих проблем в вашем реальном коде.
0 голосов
/ 10 ноября 2011
newIng.parentIng = parentIngObj.id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...