简体   繁体   中英

How can I pass a dynamic database name to a decorator?

Django has a decorator function called @transaction.commit_manually . I am attempting to pass a parameter to this decorator, (using=db) . db varies depending on which database is being used, based on business rules. What is the best way to pass the current database to this decorator? I tried to use an inner function, thus:

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()

However, this fails. The error I discovered with pdb is that the inner block is "Not under transaction management." How do I overcome this problem?

Traceback from 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"

Edit : I fixed my own problem. The internal function solution works correctly, but I needed to be calling rollback() and commit() with a using parameter, ie transaction.commit(using=db) , as well. I find that unintuitive, but...

I use this quite often in my code since I put a lot of stress on the ORM. Since I'm not a big fan of decorator syntax I use the with statement.

def do_transaction(stuff, db):
    with transaction.commit_manually(using=db)
        try:
            stuff.save(using=db)
        except:
            transaction.rollback()
        else:
            transaction.commit(using=db)

This should work. Not sure if you're going to need (using=db) in your transaction.rollback() , though. I'm sure you can do the research on that. But you do need (using=db) in transaction.commit(using=db) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM