如何将动态数据库名称传递给装饰器?
问题描述:
Django有一个名为@transaction.commit_manually
的装饰器函数。我试图传递一个参数给这个装饰器,(using=db)
。根据业务规则,db
取决于正在使用哪个数据库。将当前数据库传递给此装饰器的最佳方式是什么?我尝试使用内部函数,因此:如何将动态数据库名称传递给装饰器?
def func(db):
stuff = _business logic_
@transaction.commit_manually(using=db)
def do_transaction(stuff):
try:
stuff.save(using=db)
except:
transaction.rollback()
else:
transaction.commit()
do_transaction()
但是,这会失败。我用pdb
发现的错误是内部块“不在事务管理下”。我如何克服这个问题?
回溯从pdb
:
-> success = transactional_registration()
/usr/local/lib/python2.7/dist-packages/django/db/transaction.py(338)_commit_manually()
-> return func(*args, **kw)
> /home/syrion/dev/registration.py(59)transactional_registration()
-> transaction.rollback()
/usr/local/lib/python2.7/dist-packages/django/db/transaction.py(210)rollback()
-> set_clean(using=using)
/usr/local/lib/python2.7/dist-packages/django/db/transaction.py(125)set_clean()
-> raise TransactionManagementError("This code isn't under transaction management"
编辑:我固定我自己的问题。内部功能解决方案正常工作,但我需要使用使用参数调用rollback()
和commit()
,即使用transaction.commit(using=db)
。我发现这不直观,但...
答
我在我的代码中经常使用它,因为我在ORM上施加了很多压力。由于我不是装饰者语法的忠实粉丝,我使用with
声明。
def do_transaction(stuff, db):
with transaction.commit_manually(using=db)
try:
stuff.save(using=db)
except:
transaction.rollback()
else:
transaction.commit(using=db)
这应该有效。不过,不知道您是否需要transaction.rollback()
中的(using=db)
。我相信你可以对此进行研究。但你需要(using=db)
在transaction.commit(using=db)
。
你可以在transaction.rollback()之后添加一个raise,并发布stacktrace + full错误? – 2012-02-08 19:56:01
你为什么如此复杂?为什么func不是可调用的对象? – 2012-02-08 19:57:02
'func'是一个对象的可调用方法。如果我自己装饰'func',数据库超出范围。 – syrion 2012-02-08 20:09:55