我在学习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()我保持了这个示例的简洁性,以保持它的可读性,但是如果我遗漏了一些重要信息,请告诉我。
我假设我的问题是类实例在我递归时失去了作用域,但是将全局变量添加到列表变量似乎并没有解决这个问题。我还认为,会话充当某种缓冲区这一事实可以处理任何作用域问题。
这跟eager loading有关系吗?我在文档中看到了这一点,但我并不真正理解它。
我得到的错误是:
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)发布于 2011-11-11 17:05:13
我认为你有几个bug/输入错误,导致你的代码不能工作。我假设您创建了一个小的代码示例来显示问题,我希望一旦您修复了原始代码中的这些问题,您的问题也将得到解决:
newIng.parentIng = parentIngObj,你应该有newIng.parent = parentIngObj。我相信这应该可以解决这个问题。因此,您必须将父实例分配给relationship对象,而不是它的键。如果对象已经存储在数据库中,那么使用J.F.Sebastian的建议也是可行的,但是新实例没有为yet
addIngredient(...)分配id。vice-versa
id:参数ingredient应该重命名为ingName或vice-versaingName不返回任何值,因此实际上您将None分配给关系的parent一端。同样,由于这只是一段示例代码,因此在实际的code.中可能不会出现这些问题
发布于 2011-11-10 08:32:11
newIng.parentIng = parentIngObj.idhttps://stackoverflow.com/questions/8062157
复制相似问题