如何将动态数据库名称传递给装饰器?

时间:2012-02-08 19:28:00

标签: python django orm decorator

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"

编辑:我修复了自己的问题。内部函数解决方案正常工作,但我需要使用using参数调用rollback()commit(),即transaction.commit(using=db)。我发现这不直观,但是......

1 个答案:

答案 0 :(得分: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)

这应该有效。但是,不确定您(using=db)中是否需要transaction.rollback()。我相信你可以对此进行研究。但您需要(using=db)中的transaction.commit(using=db)