2012-02-08 70 views
3

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)。我发现这不直观,但...

+0

你可以在transaction.rollback()之后添加一个raise,并发布stacktrace + full错误? – 2012-02-08 19:56:01

+0

你为什么如此复杂?为什么func不是可调用的对象? – 2012-02-08 19:57:02

+0

'func'是一个对象的可调用方法。如果我自己装饰'func',数据库超出范围。 – syrion 2012-02-08 20:09:55

回答

1

我在我的代码中经常使用它,因为我在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)

相关问题