2

I have 2 databases:

# Config
DATABASES = {
    'default': {},
    'readonly': {},
}

In a background task, I would like to pull data from the "readonly" database, then save using the "default" database:

# Tasks
things = Thing.objects.using('readonly').all()


util.do_stuff_with_things(things)  # ideally I don't want to make `using` a required parameter of all my utilities

I could manually specify save(using='default') on all of the utilites, but it's difficult to hunt them down. I would rather commit the transaction, then start a new transaction on the default connection.

What I have attempted:

  1. set_autocommit
transaction.set_autocommit(False, using='readonly')
thing = Thing.objects.using('readonly').first()
transaction.commit(using='readonly')

transaction.set_autocommit(True, using='default')
thing.save()  # `save` still requires `using='default'`, "InternalError: cannot execute UPDATE in a read-only transaction"
  1. pulled within atomic block
with transaction.atomic(using='readonly'):
    thing = Thing.objects.using('readonly').first()


thing.save()  # `save` still requires `using='default'`, "InternalError: cannot execute UPDATE in a read-only transaction"
  1. overwriting _state.db

This works -- but I don't like it :(

thing = Thing.objects.using('readonly').first()

thing._state.db = 'default'

thing.save()

For now, I will probably go with #3, as it's least intrusive to the utilities I am using. But interested to know if there's a better way!

1

1 Answer 1

0

Thanks @arakkal-abu, Database Routers are what I was looking for

class BGTaskDatabaseRouter:
    def db_for_read(self, model, **hints):
        return 'readonly'

    def db_for_write(self, model, **hints):
        return 'default'

in my settings file:

DATABASE_ROUTERS = []
if IS_BACKGROUND_TASK:
    DATABASE_ROUTERS.append('database_routers.BGTaskDatabaseRouter'
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.